lienhua34
2014-10-02
1 进程的终止方式
进程的终止方式有 8 种,其中 5 种为正常终止,它们是
1. 从 main 返回。
2. 调用 exit。
3. 调用_exit 或_Exit。
4. 最后一个线程从其启动例程返回。
5. 最后一个线程调用pthread_exit。
另外三种为异常终止方式,它们是
1. 调用 abort。
2. 接到一个信号并终止。
3. 最后一个线程对取消请求做出响应。
2 exit 函数
有三个函数用于正常终止一个程序:_exit 和_Exit 立即进入内核,exit 则先执行一些清理处理(包括调用执行各终止处理程序,关闭所有标准 I/O 流等),然后进入内核。
#include <stdlib.h>
void exit(int status);
void _Exit(int status);
#include <unistd.h>
void _exit(int status);
三个 exit 函数都带一个整型参数,称之为终止状态(或退出状态,exit status)。main 函数返回一个整型值与用该值调用 exit 是等价的,即 exit(0)等价于 return(0)。
如果(a)main 执行了一个无返回值的 return 语句,或(b)main 没有声明返回类型为整型,则该进程的终止状态是未定义的。若 main 函数的返回类型是整型,并且 main 执行到最后一条语句时隐形返回(没有显示使用 return 或者调用 exit 函数),历史版本的终止状态是未定义的,而 ISOc 标准 1999 规定该进程的终止状态为 0.
3 终止处理程序
前面一节讲到调用 exit 函数,在进入内核之前,进程会调用一些终止处理程序(exit handler)。我们可以通过调用 atexit 函数注册终止处理程序。按照 ISO C 的规定,一个进程可以注册多达 32 个终止处理函数。
#include <stdlib.h>
int atexit(void (*func)(void));
返回值:若成功则返回0,若出错则返回非0值。
atexit 的参数是一个函数地址,注册的函数没有参数也没有返回值。exit 调用这些函数的顺序与它们注册时候的顺序相反。同一个函数如果被注册多次,则也会被调用多次。
例子:
#include <stdlib.h> #include <stdio.h> #include <string.h> #include <errno.h> static void my_exit1(void); static void my_exit2(void); int main(void) { if (atexit(my_exit2) != 0) { printf("can‘t register my_exit2: %s\n", strerror(errno)); } if (atexit(my_exit1) != 0) { printf("can‘t register my_exit1: %s\n", strerror(errno)); } if (atexit(my_exit1) != 0) { printf("can‘t register my_exit1: %s\n", strerror(errno)); } printf("main is done\n"); exit(0); } static void my_exit1(void) { printf("first exit handler\n"); } static void my_exit2(void) { printf("second exit handler\n"); }
编译该程序,生成 atexitdemo 文件,然后执行该文件,
lienhua34:demo$ gcc -o atexitdemo atexitdemo.c lienhua34:demo$ ./atexitdemo main is done first exit handler first exit handler second exit handler
(done)