有八种方法可以让进程终止(termination),前五种为正常终止:
- 从main返回
- 调用exit
- 调用_Exit 或者_exit
- 最后一个线程从其启动例程返回
- 最后一个线程调用pthread_exit返回
异常终止有三种:
- 调用abort
- 结合搜到一个信号
- 最后一个线程对取消请求做出响应
启动例程:由于main函数是被启动例程调用的,所以从main函数return时仍返回到启动例程中, main函数的返回值被启动例程得到,如果将启动例程表示成等价的C代码(实际上启动例程一般是直接用汇编写的),则它调用main函数的形式是:
exit(main(argc, argv));
也就是说,启动例程得到main函数的返回值后,会立刻用它做参数调用exit函数。也就是说第一种方法最终也是由第二种方法exit来实现的。
1、退出函数
有三个函数用于正常终止一个程序:_exit和_Exit立即进入内核,而exit则先执行一些清理处理,然后返回内核,主要是执行一个标准IO 的清理关闭操作以及执行终止处理程序(第二小节):对于所有打开的流都调用fclose函数,这将造成输出缓冲中的所有数据都被冲洗到文件上。
三个函数都有一个整型参数,称作为终止状态,一般设立了会提供检查进程终止状态的方法(如下),如果没有带参数,或者main没有return一个整数,那这个状态是未定义的:
#include <stdlib.h>
int main(void)
{
exit(4);
}
这样和int main(void) { return 4; }的效果是一样的。在Shell中运行这个程序并查看它的退出状态:
./a.out
echo $?
4
2、函数atexit
一个进程可以登记多达32个终止处理函数,使用的终止处理函数的注册函数原型为:
#include <stdlib.h>
int atexit(void (*func)(void));
exit函数调用这些函数的顺序与他们登记时候的顺序相反。同一个函数如若登记多次,也会被调用多次,但是如果程序调用exec函数组中的任一个函数,则会清除所有已安装的终止处理程序
如上图所示,内核使程序执行的唯一方法是调用exec,进程自愿终止的方法是调用exit(会调用终止处理函数和完成标准IO清理)或者_exit(直接返回到内核)
?
|