进程退出return、exit()、_exit()、进程等待(接儿子放学咯)。
创建
Linux 系统中,用户创建子进程的唯一方法就是使用 fork 系统调用。
退出
一个程序(进程)退出了,无非有一下几种情况:
- 代码运行完毕,结果正确
- 代码执行完毕,结果不正确
- 代码异常终止
之前看GitHub上别人代码里用 exit(1)
这样的方式写,虽然知道他就是结束程序,但并不知道具体的意思。查下资料吧。
常见退出方法
- 正常终止
- main 函数 return
- 调用 exit
- 调用 _exit 系统调用
- 异常终止
- ctrl + c、ctrl + d之类的
- 程序异常(比如除数为0等)
_exit 系统调用
1 | man _exit |
status 定义了进程的终止状态,父进程通过 wait 来获取该值,在 bash 中使用 $?
来看上一个进程(程序)的退出码。虽然 status 是 int,但是仅有低8位可以被父进程所用。所以_exit(-1)
时,在终端执行$?
发现返回值
是255。
exit 库函数
1 | SYNOPSIS |
这是一个 C 的库函数,本质上调用了 _exit,有一些区别:
关闭了文件流并刷新了缓冲区,通过简单的代码即可实验验证
exit 比 _exit 多调用了一个结束处理函数( atexit/on_exit 函数,参数是一个函数指针,这个好比vue中的生命周期钩子函数)
1
2
3
4
5
6
7man atexit
NAME
atexit -- register a function to be called on exit
SYNOPSIS
#include <stdlib.h>
int atexit(void (*function)(void));
int atexit_b(void (^function)(void));
return
return是一种更常见的退出进程方法。执行return n
等同于执行exit(n)
,因为调用main的运行时函数会将main的返回值当做 exit 的参数。
等待
进程状态,子进程退出,父进程不管不顾就可能造成”僵尸🧟♀️”进程,造成内存泄漏。交给子进程的任务也不知道他完成的怎么样了,父进程为了获取子进程完成任务的情况以及回收资源,可以通过进程等待的方式进行。
wait
1 | man 2 wait |
wait 是一个阻塞式函数。
wait 的调用次数必须和子进程的个数一致,少了导致僵尸进程,多了出错。
如果有多个子进程,任何一个子进程的结束都会触发 wait。
waitpid
1 | SYNOPSIS |
如果子进程已经退出,调用wait/waitpid时,wait/waitpid会立即返回,并且释放资源,获得子进程退出信息。
如果在任意时刻调用wait/waitpid,子进程存在且正常运行,则进程可能阻塞。
如果不存在该子进程,则立即出错返回。
注意 status
wait 和 waitpid 的参数 status 不关心可以填 NULL,但如果关心,还得注意一下。
这个status是由操作系统填充的,他并不真的、简单的当做一个 int 类型。status 的低 16 位是真正我们关心的。
代码实践
阻塞式
1 | include <stdio.h> |
测试:
非阻塞轮询
参考:
https://blog.csdn.net/zhangxiao93/article/details/72859312
https://www.cnblogs.com/LUO77/p/5804436.html