进程(五)—— 进程退出、进程等待(waitpid函数)

我们常常在main函数的最后看到 return 0

问:main函数中的return 与普通函数中的return有什么区别??

答:main函数的return值是进程的退出码

        非main函数退出只是函数返回

        如:main函数中的 return 0,表示退出当前进程,退出码是0(0表示正常退出)

                函数的return 0,表示退出当前函数,函数的返回值是0


目录

一、进程退出

1、进程退出的场景

2、进程退出的常见方法

(1) main函数中使用return

(2) 调用exit函数

(3) 调用 _exit 函数

(4) exit函数和_exit函数的关系

 二、进程等待

 1、进程等待函数waipid

2、关于参数status

(1) 正常退出时

(2) 异常退出时

(3) 如何取出退出码和中止信号

3、进程阻塞等待的方式

4、进程非阻塞等待的方式


一、进程退出

进程退出的时候,会返回一个退出码,这个退出码 代表当前进程的退出状态

每一个退出码对应 不同的退出状态信息

退出码由父进程接收,让父进程了解子进程的退出信息

运行pwd命令本质上都是 创建子进程,然后运行对应的程序,退出码会由bash接收

1、进程退出的场景

- 正常退出,结果正确/不正确

- 代码异常退出

2、进程退出的常见方法

(1) main函数中使用return

int main()
{
    return 2;
}

 echo $?  打印距离现在最近一次进程的退出码

(2) 调用exit函数

exit函数的参数是  当前进程要返回的退出码,可以在任意位置调用,即便是在普通的函数中也可以调用。(main函数退出的时候,即便不加 return 0,也会隐式调用exit非main函数不会隐式调用exit函数

(3) 调用 _exit 函数

_exit函数的参数是  当前进程要返回的退出码,同样可以在任意位置调用,即便是在普通的函数中也可以调用

 (4) exit函数和_exit函数的关系

exit 最后也会调用 _exit函数,但exit在中止进程的同时,还会刷新缓冲区、关闭流等

 二、进程等待

前面提到这么一个问题

父进程在忙,子进程结束了,但无人回收,这样就造成了“死亡”的子进程一直占用资源

这个时候的子进程被称为“僵尸进程”

为了解决这个问题,最初的思路是:让父进程停下,等待子进程执行完,然后回收子进程

        

 1、进程等待函数waipid

当子进程中出现exit 或者 _exit函数的时候,子进程结束

waitpid 可以接收指定子进程或者任意子进程的退出码

 参数:

        pid:pid = -1时,表示等待任意一个子进程,和wait等价

                pid > 0,等待指定子进程

        status:输出型参数,获取子进程的退出状态码

        options:

                0:阻塞等待,默认行为(也就是干等着子进程运行完,什么都不干)  

                           

                WNOHANG:非阻塞等待,相当于隔一小段时间去检测子进程是否结束,如果结束了,

                                则回收子进程;如果没有结束,则继续忙自己的事

                           

 返回值:

        回收子进程以后,返回收集到的子进程的pid

        如果设置了WNOHANG,若检测到子进程还在运行,则返回0

                                                若检测到子进程运行结束,返回子进程的pid

2、关于参数status

status不能简单的当作整型来看,要从二进制的角度来看,32位下,整型转化为二进制有32个bit位

但是我们仅关注低16位

(1) 正常退出时

进程正常退出时,子进程会返回退出码,即退出状态,8~15位记录着正常退出时的退出码,既然是正常退出就不会收到中止信号,所以0~7位都是 0

(2) 异常退出时

进程异常退出时,一般会收到一个中止进程的信号,而且不会执行到return 这句,所以自然就没有退出码,为了知道发生了何种异常,我们使用低 7 位,也就是 0~6 来记录 “中止信号”

 注意:core dump是指在进程异常退出的时候,进程会把用户空间的内存数据保存到磁盘文件,文件名为core

(3) 如何取出退出码和中止信号

方式一:

中止信号是低7位,也就是0~6 的位置,我们可以让status按位与0x7F,那么0111 1111 中1对应的位置会被保留 ——》 status & 0x7F

退出码是高8位,我们先将这8位二进制退出码右移8位到 较低的8位,然后像上面那样按位与0xFF

那么1111 1111 中1对应的位置会被保留 ——》 (status >> 8) & 0xFF

方式二:

使用系统提供的宏函数WIFEXITED(status)、 WEXITSTATUS(status)        

WIFEXITED(status) :判断进程是否正常退出,如果正常退出,返回true

WEXITSTATUS(status): 返回子进程的退出码

WIFSIGNALED(status):判断子进程是否被信号结束

WTERMSIG(status):获取结束子进程的信号类型

3、进程阻塞等待的方式

第11行,子进程退出,返回退出码为3

第21行,成功回收子进程,打印子进程的退出码,结果为3

4、进程非阻塞等待的方式

第12行,子进程退出,返回退出码为3

第22行,父进程反复检测子进程是否结束运行,若未结束,则打印"child process is running"

(这句话可以替换为父进程要执行的任务)

 采用非阻塞等待的方式,在解决僵尸进程的同时,也处理了父进程自己的任务

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值