一、进程等待

所谓的进程等待就是父进程等待子进程退出。父进程等待子进程退出其目的就是:

  1. 获取子进程的退出返回值
  2. 释放子进程的资源,避免产生僵尸进程。(僵尸进程会造成内存泄露)

进程等待有2种方式,下面分别介绍:

  1. pid_t wait(int* status);

等待任意一个子进程退出(只要有子进程,就会处理)。

参数列表:status(指针):获取子进程退出返回值。
返回值: pid_t分为2种情况:
(1)如果成功,返回子进程的pid
(2)如果失败,返回-1

wait接口是一个阻塞函数,所谓的阻塞就是为了完成一个功能,发起调用,若当前不具备完成条件,则一直等待。(就好比你去幼儿园接你娃,你没有接到你的娃,你就会一直等着(总不可能你等一会直接回家了))。

  1. pid_t waitpid(pid_t pid,int* status, int options);
    可以等待任意一个子进程退出,也可以等待一个指定的子进程退出。可以默认位阻塞接口,也可以默认为非阻塞接口。

所谓的非阻塞就是为了完成一个功能,发起调用,若当前不具备完成条件,则报错返回。

参数列表:

  1. pid_t pid:当pid = -1的时候,表示等待任意一个子进程;当pid > 0的时候,表示等待指定的子进程。
  2. status:获取子进程的退出返回值。这个status指针包含了退出返回值(高8位)、core dump文件(1位)、异常信号值(低7位);

Notes:对于异常信号值来说,当异常信号值为0,表示进程正常退出,若不为0表示进程异常退出。

如何获取异常退出信号值,有两种方法:

  1. (推荐) 使用系统调用接口:WIFEXITED(status) / WEXITEDSTATUS(status)
  2. 逻辑运算和移位操作:status & 0x7f / (status>>8)&0xff

Notes:core dump文件在程序异常退出的时候,保存进程的信息和数据,方便后期的gdb。

  1. options:0表示默认阻塞等待;用WHOHANG可以设置为非阻塞。

返回值pid_t:

当返回值大于0时,表示退出子进程的pid。当返回值等于0时候,表示没有子进程退出。错误返回-1。

下面我们来看看这两个接口的代码操作:

在这里插入图片描述
在这里插入图片描述
Notes:这里直接将waitpid第三个参数设置为WNOHANG,如果options = 0的话其实和wait没什么区别。

上面这个代码运行后还会产生僵尸进程
在这里插入图片描述
是因为waitpid等待了任意一个子进程后直接处理了,后面的子进程得不到处理,就成为僵尸进程了。为了避免这种情况,给waitpid加一个循环即可:

在这里插入图片描述

status的获取:

在这里插入图片描述
此处获取子进程退出返回值成功后status的值为99(我不小心把结果整没了。。。有一丝尴尬)。

二、程序替换

进程替换就是替换一个进程正在调度运行的程序。加载一个新的程序到内容中,更新当前进程的页表映射信息,让当前进程映射到程序上。

在这里插入图片描述

exec函数簇:

在这里插入图片描述
第一个参数:新的程序文件路径名字
第二个参数:程序的运行参数
第三个参数:程序的环境变量

举个例子:
在这里插入图片描述
在这里插入图片描述
我们可以看到上面代码执行结果并没有打印"linux真tm难"是因为执行execl替换以后就执行ls命令,执行完毕后就直接退出,所以没有打印"linux真tm难"

函数簇中,execl和execlp的区别就在于程序文件是否需要路径,有p的时候,可以不用带路径,但是有一个限制就是程序必须在PATH环境变量指定的路径下。

在这里插入图片描述
execle和execl的区别就在于:
程序是否自己设定环境变量,有e就是自己设定(覆盖式),没有e就是用默认的路径。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我们可以看到当使用execle时,环境变量就剩一个了,就是我们自己设置的。

execl和execv的区别就在:
程序运行参数的赋予方式不一样,v是传字符串指针数组。

Logo

更多推荐