《嵌入式Linux应用编程(六):并发编程基础:多进程exec函数族及多线程基础》

一、exec函数族

        在一个进程里面执行另一个文件

        本质:将文本区的指令代码替换成exec要执行的指令

#include <unistd.h>


参数:path:要执行的可执行文件的路径和名称
arg:执行该可执行文件时需要传递的参数
NULL:参数传递结束标志
返回值:错误为1,正确不返回

int execlp(const char *file, const char *arg, .../* (char  *) NULL */);

功能:从PATH指定的系统路径下寻找该可执行文件

参数:file:需要执行的可执行文件的名称(系统路径下已有的文件)

         arg:执行该可执行文件时需要传递的参数

        NULL:参数传递结束标志

int execle(const char *path, const char *arg, .../*, (char *) NULL, char * const envp[] */);

execle 函数允许自定义环境变量传递给新程序。参数 path 为可执行文件的完整路径,arg 为参数列表,envp 是一个字符串数组,表示新的环境变量(格式为 "KEY=value"),以 NULL 结尾。

int execv(const char *path, char *const argv[]);

execv 与 execl 功能相同,但参数传递方式不同。execv 使用字符串数组 argv 传递参数(数组末尾需为 NULL),适合动态生成参数的场景。

int execvp(const char *file, char *const argv[]);

execvp 结合了 execv 和 execlp 的特点:从系统路径查找可执行文件,并通过数组传递参数。参数 file 为文件名,argv 为参数数组(含命令自身)。

int execvpe(const char *file, char *const argv[],char *const envp[]);

execvpe 是 execvp 的扩展版本,支持自定义环境变量。参数 envp 为环境变量数组,格式与 execle 相同。非标准函数,需确保系统支持(如 GNU 扩展)。

代码

#include <stdio.h>int main(void)
{printf("Hello World!\n");return 0;
}

编译命令为gcc text.c -o hello

#include<stdio.h>
#include<unistd.h>int main(int argc, char const *argv[])
{//execl("./hello", "./hello", NULL);//execl("/bin/ls", "ls", "-l", NULL);//execlp("ls", "ls", "-l", NULL);//char *arg[] = {"ls", "-l", NULL};//execv("/bin/ls", arg);// char *arg[] = {"ls", "-l", NULL};// execvp("ls", arg);return 0;
}

l:list  列表
p:path  路径 : 系统路径
v:vector 容器
e:env  环境变量


二、system

system相当于调用了一次fork(),父进程等待子进程运行结束后,在进行运行

不调用system函数接口,实现system的功能


#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>int my_system(char *buff)
{char *arg[10] = {NULL};int i = 0;char cmd[512] = {0};strcpy(cmd, buff);arg[i] = strtok(cmd, " ");while (arg[i] != NULL){printf("arg[%d] = %s\n", i, arg[i]);i++;arg[i] = strtok(NULL, " ");}pid_t pid = fork();if (pid > 0){wait(NULL);}else if (0 == pid){execvp(arg[0], arg);}return 0;}int main(int argc, const char *argv[])
{printf("system : pid = %d\n", getpid());
//	system("./hello");my_system("ls -l");printf("After system\n");return 0;
}

三、线程

1.什么是线程

        轻量级的线程,可实现多任务的并发。
进程是操作系统资源分配的最小单位;
线程是操作系统任务调度的最小单位。


2.线程的创建

        线程由某个进程创建。

        进程创建线程时,会为其分配独立的8M的独立的栈区空间

        线程所在的进程,以及进程中的其他线程,共用进程的堆区、数据区、文本区。


3.线程的调度

        宏观并行,微观串行


4.线程的消亡

        1)线程退出

        2)回收线程资源空间


5.进程和线程的区别

        1)进程

        资源消耗:

                进程是操作系统资源分配的最小单位;

                资源开销大,每次创建都需要0-4G的虚拟空间

        效率方面:

                由操作系统创建,耗时比线程久;跨进程调度比跨线程慢

        通信方面:

                进程间不能之间通信,需要使用进程间通信机制(IPC)机制

        安全性角度:

                进程安全性比线程高,各进程空间独立


        2)线程

        资源消耗:

                线程是操作系统任务调度的最小单位。

                资源开销小,只需要所在进程为其开辟8M的栈区空间

        效率方面:

                        由所在进程创建跨进程调度比跨线程调度慢:

        通信方面:

                        通信简单,可以使用线程共享的区域进行通信(比如全局变量)

        安全性角度:

                        线程没有进程安全,一个线程异常可能影响同一进程中所有线程


6.线程的相关编程

1)线程的创建

#include <pthread.h>int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);

功能:

        创建一个新线程

参数:

        thread:保存线程ID的变量地址

        attr:线程属性的对象地址

        NULL:按照默认属性创建

         void *(*start_routine) (void *):函数指针,函数名start_routine,指向线程启动后要执行的任务(线程任务函数)

        arg:为线程任务函数传递的参数

返回值:

        成功:0

        失败:非0

        pthread—self():获取当前线程ID号

        pthread_create是不是linux函数,编译和链接时要加-lpthread

        进程创建线程后,进程不能先退出,加sleep()

2)线程调度;由操作系统调度

3)线程退出

        I.线程退出

                void pthread_exit(void *retval);

                功能:退出一个线程任务

                参数:

                        retval:向回收的线程传递的参数的地址(NULL表示不传递参数)

        II.线程回收

                int pthread_join(pthread t thread, void * *retval).

                功能:回收线程资源空间

                参数:
thread:要回收的线程ID

                        retvaf用来保存线程退出时传递的参数(NULL表示不传递参数)

                返回值:

                        成功:0

                        失败-1

                III:线程属性

                        1.分离属性:不需要被其他线程回收的线程称为分离属性得到线程,将来会被操作系统所回收

                int pthread_detach(pthread_t thread);

                功能:将线程设置为分离属性的线程

                        2.非分离属性:可以被其他线程回收或者结束的线程,称为非分离属性的线程(默认属性:非分离属性)

                IV:线程回收策略:

                1.分离属性的线程:不需要回收。(没有空闲的线程可以帮忙回收时)

                2.非分离属性的线程:pthread_join()阻塞回收

7.线程间通信

        全局变量通信

        临界资源:多个线程可以同时访问的资源称为临界资源:比如,全局变量、共享内存区域等

        如何解决资源竞争问题:

                1)互斥机制:多个线程访问临界资源时,具有排他性访问的机制(一次只允许一个线程对该临界资源进行访问)

                互斥锁->解决资源竞争问题。

                步骤:

                        1.创建互斥锁:pthread_utex_t 

                        2.初始化互斥锁:pthread_mutex_init

                        3.加锁:pthread_mutex_lock

                        4.解锁:pthread_mutex_unlock

                        5.销毁锁:pthread_mutex_destroy

int pthread mutex init(pthread mutex t *restrict mutex.const pthread mutexattr t*restrict attr)

        功能:初始化互斥锁

        参数:mutex:锁对象地址
attr:锁的属性(NULL:默认属性)

        返回值:成功:0

                     失败:-1

 int pthread_mutex_lock(pthread_mutex_t *mutex);

        功能:加锁

int pthread_mutex_unlock(pthread_mutex_t *mutex);

        功能:解锁

int pthread_mutex_destroy(pthread_mutex_t *mutex);

        功能:销毁锁


四、线程相关代码

1.创建线程
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
void *task(void *arg)
{printf("I am thread : tid = %ld\n", pthread_self());
}int main(int argc, char const *argv[])
{pthread_t tid;int ret = pthread_create(&tid, NULL, task, NULL);if(ret != 0){printf("pthread_create error\n");return -1;}sleep(2);return 0;
}

2.让线程输出一个学生的信息

#include<stdio.h>
#include<pthread.h>
#include<unistd.h>struct stu
{int id;char name[20];
}Stu;void *task(void *arg)
{struct stu *student = (struct stu *)arg;  printf("%d\n%s\n", student->id, student->name);return NULL;
}int main(int argc, char const *argv[])
{pthread_t tid;struct stu s = {1,"wang"};int ret = pthread_create(&tid, NULL, task, &s);if(ret != 0){printf("pthread_create error\n");return -1;}sleep(1);return 0;
}

3.线程模拟无人机工作

#include<stdio.h>
#include<pthread.h>
#include<unistd.h>void *task1(void *arg)
{ while(1){printf("主控模块正在运行\n");pthread_exit(NULL);}
}void *task2(void *arg)
{ while(1){printf("控制模块正在运行\n");pthread_exit(NULL);}
}void *task3(void *arg)
{ while(1){printf("图像采集模块正在运行\n");pthread_exit(NULL);}
}void *task4(void *arg)
{ while(1) {printf("图像发送模块正在运行\n");pthread_exit(NULL);}
}void *task5(void *arg)
{ while(1){printf("指令接收模块正在运行\n");pthread_exit(NULL);}
}int main(int argc, char const *argv[])
{pthread_t tid1;pthread_t tid2;pthread_t tid3;pthread_t tid4;pthread_t tid5;int ret1,ret2,ret3,ret4,ret5;ret1 = pthread_create(&tid1, NULL, task1, NULL);ret2 = pthread_create(&tid2, NULL, task2, NULL);ret3 = pthread_create(&tid3, NULL, task3, NULL);ret4 = pthread_create(&tid4, NULL, task4, NULL);ret5 = pthread_create(&tid5, NULL, task5, NULL);if(0 != ret1 && 0 != ret2 && 0 != ret3 && 0 != ret4 && 0 != ret5){printf("pthread_create error\n");return -1;}sleep(1);pthread_join(tid1, NULL);pthread_join(tid2, NULL);pthread_join(tid3, NULL);pthread_join(tid4, NULL);pthread_join(tid5, NULL);return 0;
}

4.加互斥锁解决资源竞争问题

#include <stdio.h>
#include <pthread.h>int num_g = 0;
pthread_mutex_t mutex;void *task1(void *arg)
{for (int i = 0; i < 100000; i++){pthread_mutex_lock(&mutex);num_g = num_g+1;printf("num_g = %d\n", num_g);pthread_mutex_unlock(&mutex);}
}void *task2(void *arg)
{for (int i = 0; i < 100000; i++){pthread_mutex_lock(&mutex);num_g = num_g+1;printf("num_g = %d\n", num_g);pthread_mutex_unlock(&mutex);}}int main(int argc, const char *argv[])
{pthread_t tid[2];pthread_mutex_init(&mutex, NULL);pthread_create(&tid[0], NULL, task1, NULL);pthread_create(&tid[1], NULL, task2, NULL);pthread_join(tid[0], NULL);pthread_join(tid[1], NULL);pthread_mutex_destroy(&mutex);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/918916.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/918916.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【121页PPT】智慧方案智慧综合体智能化设计方案(附下载方式)

篇幅所限&#xff0c;本文只提供部分资料内容&#xff0c;完整资料请看下面链接 https://download.csdn.net/download/2501_92808859/91654007 资料解读&#xff1a;【121页PPT】智慧方案智慧综合体智能化设计方案 详细资料请看本解读文章的最后内容 一、项目概述与智能化总…

Linux网络基础(一)

目录 计算机网络背景 网络发展 初识 "协议" 网络协议初识 协议分层 软件分层的好处 打电话例子 OSI七层模型 TCP/IP五层(或四层)模型 参考资料 再识协议 为什么要有 TCP/IP 协议&#xff1f; 什么是 TCP/IP 协议&#xff1f; TCP/IP 协议与操作系统的关系(宏观上&…

MySQL多表查询案例

多表查询本文介绍了多表查询中的表关系概念和操作方法。主要内容包括&#xff1a;1.三种表关系类型&#xff08;一对多、多对多、一对一&#xff09;及其实现方式&#xff1b;2.多表查询的四种连接方式&#xff08;内连接、左外连接、右外连接、自连接&#xff09;及语法&#…

Dify 从入门到精通(第 36/100 篇):Dify 的插件生态扩展

Dify 从入门到精通&#xff08;第 36/100 篇&#xff09;&#xff1a;Dify 的插件生态扩展 Dify 入门到精通系列文章目录 第一篇《Dify 究竟是什么&#xff1f;真能开启低代码 AI 应用开发的未来&#xff1f;》介绍了 Dify 的定位与优势第二篇《Dify 的核心组件&#xff1a;从…

【已解决】在Spring Boot工程中,若未识别到resources/db文件夹下的SQL文件

在Spring Boot工程中&#xff0c;若未识别到resources/db文件夹下的SQL文件&#xff0c;通常与资源路径配置、构建工具设置或代码加载方式有关。以下是逐步排查和解决方案&#xff1a;​​1. 确认SQL文件存放路径​​Spring Boot默认从类路径&#xff08;classpath:&#xff09…

【Java】网络编程(4)

1. 再谈 UDP 报文长度&#xff1a;也是 2 个字节&#xff0c; 0 - 65535&#xff0c;也就是 64 kb。这表示一个 UDP 数据包一次最多只能传输 64 kb 的数据校验和&#xff1a;验证数据是否在传输过程中发生修改。数据在传输过程中可能受到信号干扰&#xff0c;发生 “比特翻转”…

QT(事件)

一、事件前言事件是QT的三大机制之一&#xff0c;一定程度上信号和槽也属于事件的一种 QT中的事件指哪些&#xff1a;窗口关闭&#xff0c;窗口显示&#xff0c;敲击键盘&#xff0c;点击鼠标左键、鼠标右键、鼠标滚轮&#xff0c;文件拖放等等1、事件循环QT中的所有事件&#…

基于 Vue2+Quill 的富文本编辑器全方案:功能实现与样式优化

在 Web 开发中&#xff0c;富文本编辑器是内容管理系统、博客平台等应用的核心组件。本文将详细介绍如何基于 Vue 和 Quill 构建一个功能完善、样式精美的富文本编辑器&#xff0c;重点解决字体字号选项冗长、样式不美观及功能完整性问题&#xff0c;提供可直接部署使用的完整方…

C#内嵌字符串格式化输出

内嵌字符串格式输出 double speedOfLight 299792.458;System.Globalization.CultureInfo.CurrentCulture System.Globalization.CultureInfo.GetCultureInfo("nl-NL"); string messageInCurrentCulture $"The speed of light is {speedOfLight:N3} km/s.&quo…

ThreeJS程序化生成城市大场景底座(性能测试)

一、简介基于矢量geojson数据构建建筑、植被、道路等&#xff0c;实现城市场景底座。涉及渲染的性能优化无非就是众所周知的那些事儿。视锥剔除、mesh合并、减少draw call、四叉树、八叉树、数据压缩、WebWorker、着色器优化等。下面是对东莞市数十万建筑以及海量3D树的渲染测试…

​电风扇离线语音芯片方案设计与应用场景:基于 8 脚 MCU 与 WTK6900P 的创新融合

​电风扇离线语音芯片方案设计与应用场景&#xff1a;基于 8 脚 MCU 与 WTK6900P 的创新融合一、引言在智能家居领域蓬勃发展的当下&#xff0c;用户对于家电产品的智能化和便捷性需求日益增长。传统的电风扇控制方式&#xff0c;如按键操作或遥控器控制&#xff0c;在某些场景…

(第四篇)spring cloud之Consul注册中心

目录 一、介绍 二、安装 三、整合代码使用 1、创建服务提供者8006 2、创建服务消费者80 3、Eureka、zookeeper和consul的异同点 一、介绍 Consul 是一套开源的分布式服务发现和配置管理系统&#xff0c;由 HashiCorp 公司用 Go 语言开发。它提供了微服务系统中的服务治理…

NAT 和 PNAT

核心概念与背景 IPv4 地址枯竭&#xff1a; IPv4 地址空间有限&#xff08;约 42.9 亿个&#xff09;&#xff0c;早已分配殆尽。NAT/PNAT 是缓解此问题的最重要、最广泛部署的技术。私有 IP 地址空间&#xff1a; IANA 保留了三个 IPv4 地址段专供私有网络内部使用&#xff08…

windows系统创建FTP服务

一丶开启FTP功能 控制面板->程序与功能->启用或关闭windows功能->Internet Information Services->勾选FTP服务器二丶创建FTP服务 1丶控制面板->windows工具->Internet Information Services (IIS) 管理器2丶网站->添加FTP站点->输入对应内容3丶点击新…

DeepSeek补全IBM MQ 9.4 REST API 执行命令的PPT

DeepSeek补全了我在网上找到的PPT的一页内容&#xff0c;帮了大忙了。人机协同&#xff0c;人工智能可以协助人更好的做事。下面的内容是讲解IBM MQ REST API 执行IBM MQ命令的PPT: MQSC for REST Tailored RESTful support for individual MQ objects and actions are in the …

【swift】SwiftUI动画卡顿全解:GeometryReader滥用检测与Canvas绘制替代方案

SwiftUI动画卡顿全解&#xff1a;GeometryReader滥用检测与Canvas绘制替代方案一、GeometryReader的性能陷阱深度解析1. 布局计算机制2. 动画中的灾难性表现二、GeometryReader滥用检测系统1. 静态代码分析器2. 运行时性能监控三、Canvas绘制优化方案1. 基础Canvas实现2. 性能优…

悄悄话、合唱层次感:声网空间音频解锁语聊新玩法

作为语聊房主播&#xff0c;我曾觉得线上相聚差点意思。多人开麦时声音混杂&#xff0c;互动缺真实感&#xff0c;观众留不住&#xff0c;自己播着也没劲。直到平台接入声网空间音频&#xff0c;一切改观&#xff0c;观众说像在真实房间聊天&#xff0c;留存率涨 35%&#xff0…

【工具】多图裁剪批量处理工具

文章目录工具核心功能亮点1. 批量上传与智能管理2. 精准直观的裁剪控制3. 一键应用与批量处理为什么这个工具能提升你的工作效率&#xff1f;统一性与一致性保证节省90%以上的时间专业级功能&#xff0c;零学习成本实际应用场景电子商务摄影工作内容创作教育领域技术优势完全在…

如何提升需求分析能力

要系统性地提升需求分析能力&#xff0c;核心在于实现从一个被动的“需求记录员”&#xff0c;向一个主动的、价值驱动的“业务问题解决者”的深刻转型。要完成这一蜕变&#xff0c;必须在五个关键领域进行系统性的修炼与实践&#xff1a;培养“穿透表象”的系统思维能力、掌握…

另类的pdb恢复方式

cdb中有pdb1,pdb2 需求&#xff1a;希望将在线热备份pdb1的备份集a&#xff0c;恢复成pdb3&#xff0c;使得cdb中有pdb1,2,3 参考到的&#xff1a;RMAN备份恢复典型案例——跨平台迁移pdb - 墨天轮 ORA-65122: Pluggable Database GUID Conflicts With The GUID Of An Existi…