【Linux】详解进程控制 ( 再谈进程退出 | 程序替换exec*类型函数 )

news/2024/10/23 7:38:03/

  • 再谈进程退出
  • 进程程序替换
    • 引入
    • 程序替换原理
    • 有哪些替换函数
      • execl:
      • execlp:
      • execv:
      • execvp:
      • execle:
    • execve:

接续上篇博客 “详解进程控制 ( fork函数 | 写时拷贝 | 进程退出 | 进程等待 )”

再谈进程退出

  1. 进程退出会变成僵尸状态,将自己的推出结果写入task_struct
  2. wait与waitpid是一个系统调用,操作系统有资格也有能力去读取子进程的task_struct
  3. wait与waitpid就是从退出子进程的task_struct中获取的

感性认识阻塞与非阻塞:

假设张三喊李四去吃饭,张三给李四打电话,但是李四说他还有事大概需要等30分钟,这时候张三:
1.张三不挂电话,一直等到李四说我好了然后去吃饭 ----- 阻塞
2.张三把电话挂了,然后去做自己的事情边做边等,过个几分钟给李四打电话问他好了没,过个几分钟又打电话……-----每一次打电话都是一次非阻塞等待(多次非阻塞等待\轮询
打电话对应的是系统调用wait\waitpid, 张三(父进程)、李四(子进程)

轮询访问父进程代码:

//父进程
int status = 0;
while(1)
{pid_t ret = waitpid(id, &status, WNOHANG); //WNOHANG: 非阻塞-> 子进程没有退出, 父进程检测时候,立即返回if(ret == 0){// waitpid调用成功 && 子进程没退出printf("wait done, but child is running...., parent running other things\n");}else if(ret > 0){// 1.waitpid调用成功 && 子进程退出了printf("wait success, exit code: %d, sig: %d\n", (status>>8)&0xFF, status & 0x7F);break;}else{// waitpid调用失败,比如我的waitpid的函数参数id写错printf("waitpid call failed\n");break;}sleep(1);
}

运行结果:
在这里插入图片描述

非阻塞状态有什么好处?不会占用父进程的所有精力,可以在轮询期间干干别的事情。

进程程序替换

创建子进程目的:

  • 想让子进程执行父进程代码的一部分(执行父进程对应的磁盘代码中的一部分)
  • 想让子进程执行一个全新的程序(让子进程想办法,加载磁盘上指定的程序,执行新程序的代码和数据)

引入

int execl(const char *path, const char *arg, ...);
//将指定的程序加载到内存中,让指定进程进行执行
//path是用来找到这个程序,如何执行就是后面的arg传入的选项

比如:

  1 #include <stdio.h>2 #include <unistd.h>3 int main()4 {5     printf("process is running...\n");6 7     execl("/usr/bin/ls","ls",NULL);8 9     printf("process is done...\n");10     return 0;11 }

在这里插入图片描述
运行结果:
在这里插入图片描述
我将增加几个执行选项,并加上颜色显示:

execl("/usr/bin/ls","ls","--color=auto","-a","-l",NULL); 

在这里插入图片描述

上述过程就是程序替换,我们只要能找到这个程序,然后添加它的运行选项就可以执行。

程序替换原理

我们看之前的代码打印出来的结果:
在这里插入图片描述
程序执行图:
在这里插入图片描述
为什么后一个printf没有执行?
 printf也是代码,且在execl函数之后,execl函数执行完毕的时候,代码已经全部被复制,开始执行新的程序的代码了,所以printf就无法执行。
 execl是一个函数,而一个函数的调用就有可能成功有可能失败,调用失败就是没有替换成功,也就是没替换,所以会继续执行原代码:
在这里插入图片描述
 exec*没有成功返回值,因为成功了就与接下来的原代码无关,判断没有意义。execl只要返回了,一定是错误了。
在这里插入图片描述
在这里插入图片描述

父进程创建子进程,子进程的替换会影响父进程吗?

  1 #include <stdio.h>2 #include <unistd.h>3 #include <stdlib.h>4 #include <assert.h>5 #include <sys/types.h>6 #include <sys/wait.h>7 8 int main()9 {10     printf("process is running...\n");11     pid_t id  = fork();12     assert(id != -1);13     if(id==0)14     {15         sleep(1);16         execl("/usr/bin/ls","ls","-a",NULL);                                                                                                                                                                  17         exit(1);                                    18     }                                               19     int status=0;                                   20     pid_t ret = waitpid(id,&status,0);              21     if(ret>0)                                       22     {                                               23         printf("wait sucess : exit code:%d, signal:%d\n",(status>>8)&0xFF,status & 0x7F);24     }25		return 0;26 }

在这里插入图片描述

在这里插入图片描述
 进程具有独立性,子进程成功调用exec*会发生写时拷贝,在物理内存里面重新加载代码与数据,然后更改子进程的页表映射,此过程不会影响父进程。

虚拟地址空间+页表 : 保证了进程独立性,一旦有执行流想替换代码或数据,就会发生写时拷贝

有哪些替换函数

使用man指令查看execl函数
在这里插入图片描述
 这些函数如果调用成功则加载新的程序从启动代码开始执行,不再返回。如果调用出错则返回-1,所以exec函数只有出错的返回值而没有成功的返回值。

这些函数开头都是exec,而后面跟的字符可以代表不同含义:

  • l(list) : 表示参数采用列表
  • v(vector) : 参数用数组
  • p(path) : 有p自动搜索环境变量PATH
  • e(env) : 表示自己维护环境变量

execl:

int execl(const char *path, const char *arg, ...);

 l:list:将参数一个一个的传入exec*

替换自己写的可执行程序:

execl("./myexe","myexe",NULL);

在这里插入图片描述

程序替换,可以使用程序替换,调用任何后端语言对应的可执行–程序

execlp:

int execlp(const char *file, const char *arg, ...);
//带p无需写全路径,可以直接使用环境变量PATH
execlp("ls", "ls", "-a", "-l", "--color=auto", NULL);

 这里有两个ls, 重复吗?不重复,一个是告诉系统我要执行谁?一个是告诉系统,我想怎么执行
 p:path:如何找到程序的功能,带p字符的函数,不用告诉我程序的路径,你只要告诉我是谁,我会自动在环境变量PATH,进行可执行程序的查找!

execv:

int execv(const char *path, char *const argv[]);
char *const argv_[] = {"ls","-a","-l","--color=auto",NULL};
execv("/usr/bin/ls", argv_);

 v:vector:可以将所有的执行参数,放入数组中,统一传递,而不用进行使用可变参数方案

execvp:

int execvp(const char *file, char *const argv[]);
//将 v 与 p 的特性结合起来
char *const argv_[] = {"ls","-a","-l","--color=auto",NULL};
execvp("ls", argv_);
int main(int argc, char *argv[])
// ./exec ls -a -l -> "./exec" "ls" "-a" "-l"
execvp(argv[1], &argv[1]);

运行结果:
在这里插入图片描述

execle:

int execle(const char *path, const char *arg, ...,char *const envp[]);
//需要自己组装环境变量
char *const envp[] = {"PATH=/bin:/usr/bin", "TERM=console", NULL};
execle("ps", "ps", "-ef", NULL, envp)

 自定义环境变量举个例子:
在这里插入图片描述
 为了即使用全局环境变量又添加自己的环境变量,我们使用putenv来增加以一个环境变量:
在这里插入图片描述

在这里插入图片描述
先加载execle后执行main:
在这里插入图片描述

execve:

我们使用man手册打开它,可以知道它在2号手册里,代表他是系统调用
在这里插入图片描述

事实上,只有execve是真正的系统调用,其它五个函数最终都调用 execve,所以execve在man手册 第2节,其它函数在man手册第3节
程序替换中execve为系统调用,其它都是封装,为了让我们有更多的选择性


如有错误或者不清楚的地方欢迎私信或者评论指出🚀🚀


http://www.ppmy.cn/news/601103.html

相关文章

vue核心知识点

vue.js的两个核心是什么 数据驱动也叫双向数据绑定 Vue.数据观测管理在技术实现上,利用的是ES5Object.defineProperty和存储器属性&#xff1a;getter和setter&#xff0c;可称为基于依赖收集的观测机制。核心是VM&#xff0c;保证数据和视图的一致性 组件系统 1.模板(templat…

ffmpeg 转码异常记录

ffmpeg 转码遇到一个问题&#xff0c;目前尚未排查出原因&#xff0c;先记录下来&#xff0c;后续跟踪 背景&#xff1a;obs 采集媒体源&#xff08;该媒体源mp4,h264编码&#xff0c;无音频,音频使用本地麦克风采集&#xff09;&#xff0c;推流到srs源站&#xff0c;ffmpeg …

视频格式转码工具FFMPEG

下载地址是&#xff1a;http://ffmpeg.org/download.html 下载之后解压运行ff-prompt.bat 然后配置环境变量&#xff1a;在path中添加xx\ffmpeg-20150717-git-8250943-win64-static\bin;然后打开命令行测试ffmpeg命令出现下图 格式说明你的配置已经…

简便高效的视频转换:四种免费MP4格式转换器推荐

现代社会的高速发展带来了快节奏的生活方式&#xff0c;短视频已经成为一种流行趋势。如今&#xff0c;抖音、快手等短视频软件已成为现代人生活中必不可少的存在。许多人甚至开始亲自制作短视频&#xff0c;短视频正处于黄金时代。然而&#xff0c;有很多人不清楚有哪些免费的…

视频转码解决方案

视频转码解决方案 ASIC ASIC 优势 - 1.功耗低&#xff0c; 7W-15W功耗 2. 密度高&#xff0c;可以提供8 x 1080P60 实时转码&#xff0c;或者2 x 4KP60 3. 支持格式广&#xff0c;支持H.265(HEVC) / H.264 / VP9 10bit 4. 实时性好&#xff0c;延时低于120ms 5. TCO成本最低 …

FFMPEG开发之——视频转码

一 概述 多媒体视频处理工具FFmpeg有非常强大的视频转码功能&#xff1a; ts视频格式转换为mp4avi视频格式转换为mp4flv视频格式转换为mp4mkv视频格式转换为mp4mov视频格式转换为mp4mpg视频格式转换为mp4rmvb视频格式转换为mp4wmv视频格式转换为mp4 二 工具说明 2.1 工具说明…

腾讯视频转码

http://jingyan.baidu.com/article/624e7459b379f334e8ba5ae1.html

云转码:express-ffmpeg 免费开源云转码切片平台

云转码&#xff1a;express-ffmpeg 云转码express-ffmpeg是基于nodejs开发的云转码切片管理平台&#xff0c;源码开源并且完全免费&#xff0c;每个想要学习ffmpeg操作的人都可以安装使用&#xff0c;安装之前需要系统安装nodejs、mongodb、ffmpeg的环境&#xff0c;如果不知道…