当前位置: 首页 > ds >正文

《嵌入式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.线程退出

        II.线程回收


四、线程相关代码

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;
}

http://www.xdnf.cn/news/18046.html

相关文章:

  • swift多卡并行训练微调qwen3-8B
  • QT开发中QString是怎么转char*类型的
  • ARM Cortex-M7 Thread Mode与Handler Mode
  • 数据结构:严格二叉树 (Strict Binary Tree)
  • PyTorch的安装-CPU版本或者GPU安装有什么区别吗
  • Unity_导航网格
  • 我的第一个音乐元素浏览项目上传至Github啦!
  • MyBatis 与 MyBatis-Plus 的区别
  • STM32L051同时处理Alarm A和Alarm B中断
  • SSH协议的GIT转换
  • 系统介绍pca主成分分析算法
  • flutter开发(二)检测媒体中的静音
  • Day59--图论--47. 参加科学大会(卡码网),94. 城市间货物运输 I(卡码网)
  • 【DDIA】第二部分:分布式数据
  • 应用层协议——HTTP
  • 抽奖程序web程序
  • JavaScript 基础实战:DOM 操作、数据类型与常见需求实现
  • 项目管理工具
  • NPM 、 NPX
  • 清除 pnpm 缓存,解决不同源安装依赖包失败的问题
  • electron之win/mac通知免打扰
  • 【R语言】R 语言中 gsub 与正则表达式详解(含 POSIX 与 Perl 风格实例)
  • 汽车电子:现代汽车的智能核心
  • [激光原理与应用-287]:理论 - 波动光学 - 电磁波既能承载能量,又能承载信息?
  • 【软件设计模式】前置知识类图、七大原则(精简笔记版)
  • Spark 运行流程核心组件(二)任务调度
  • EN/IEC 55015 照明设备的电磁兼容标准安全
  • Docker Compose部署Clickhouse最新版
  • 【LINUX网络】HTTP协议基本结构、搭建自己的HTTP简单服务器
  • 为什么游戏会出现“卡顿”:`clock.tick()` v.s. `clock.get_fps()`