进程终止
一般来说,进程的退出场景有以下三种:
代码运行完毕,结果正确
代码运行完毕,结果错误
代码异常终止
常见的退出方法:
从main函数返回
调用exit
调用_exit
在Linux学习的过程中,我们常用 Ctrl+c来终止我们运行的程序,这就是异常终止
_exit函数
#include<unistd.h>
void _exit(int status);
//status定义为进程的终止状态,父进程通过wait来获取这个值
虽然status是int,但仅有低八位可以被父进程所用,所以_exit(-1)时,在终端执行$?发现返回值是255
exit函数
#include<unistd.h>
void exit(int status);
我们需要明确一点,在任何地方,一旦调用exit函数,则当前进程就会退出。
exit函数最后也会调用_exit函数,但是在调用之前,还需要做另外的一些工作:
执行用户通过atexit或者on_exit定义的清理函数
关闭所有打开的流,所有的缓存数据均被写入
调用_exit
测试代码:
一
#include<stdio.h>
#include<unistd.h>
int main()
{
printf("haha\n");
exit(0);
}
二
#include<stdio.h>
#include<unistd.h>
int main()
{
printf("haha");
_exit(0);
}
return退出
return是一种更常见的退出进程方式,执行return n等同于执行exit(n),因为调用main的函数运行时会将main的返回值当做exit的参数。
进程等待
进程等待的必要性
子进程退出,如果父进程不进行回收,就可能造成僵尸进程的问题,进而造成内存泄漏
进程一旦变为僵尸进程,则无法杀死,连kill -9命令也无能为力
父进程需要知道子进程的任务的最终执行结果
父进程需要通过进程等待的方式,回收子进程资源,获取子进程退出信息
进程等待的方法
一:wait方法
#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int *status)
返回值:成功返回被等待进程的pid,失败返回 -1 。
参数:输出型参数,获取子进程退出状态,不关心则可以设置成NULL 。
二:waitpid方法
pid_t waitpid(pid_t pid,int *status,int options);
返回值:
1-> 正常返回时返回收集到的子进程的ID。
2-> 如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0。
3-> 如果调用中出错,则返回 -1 。这时errno会被设置成相应的值以指示错误所在。
参数:
pid-> pid为-1时,等待任一个子进程,与wait等效
status->
WIFEXITED(status):若为正常终止子进程返回的状态,则为真(查看进程是否是正常退出),
WEXITSTATUS(status):若WIFEXITED非零,提取子进程退出码,(查看进程的退出码)。
options->
WNOHANG:若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待,若正常结束,则返回该子进程的ID。
若子进程已经退出,调用wait/waitpid时会立即返回并且释放资源,获得子进程退出信息
若在任意时刻调用wait/waitpid,子进程存在且正常运行,则进程可能阻塞
如果不存在该子进程,则立即出错返回