分享

Linux进程-进程的退出

 guitarhua 2012-04-16
Linux进程-进程的退出

摘自: www.  被阅读次数: 158


yangyi 于 2011-12-28 22:52:04 提供


-

    void _exit(int status)

    注意点:

    1.status表明了进程终止时的状态。当子进程使用_exit()后,父进程如果在用wait()等待子进程,那么wait()将会返回status 状态,注意只有status的低8位(0~255)会返回给父进程。通常,我们使用0,表示进程成功返回,非负值表示进程不成功返回。但是,这种约定不是 强制的,每个应用程序都可以自己指定。

    2.虽然返回值可以是0~255,但是我们通常使用0~128。因为在shell编程中,如果一个进程被信号打断,shell会返回128+信号编号。在 shell中,这两个值是没有区别的(都是当做进程返回值),如果我们进程中使用了128~255,那么就无法区别到底是信号打断还是进程自己退出了。

    void exit(int status)

    注意点:

    1.在exit()调用后,退出处理函数(exit handler)首先被执行(这些函数使用atexit()和on_exit()注册)。

    2.stdio流缓冲区被刷新。(还有其他资源的清理)

    3.最后一步才是调用_exit()退出。

    4.在main函数中最后调用return n和调用exit()是相同的作用。如果在main函数最后调用return或不调用任何退出函数,调用main的运行时函数会自动的调用exit(), 但是status会变得不确定(在C89中,status可能会是栈中的某个值,或CPU寄存器中的某个值,这要看编译器是怎么使用的。在C99中,要求 status必须是0)。

    注册退出处理函数

    在程序退出之前,我们都会主动地做一些清理的动作,比如把程序缓冲区的数据保存在文件上。通常的做法是在exit()之前,调用一些清理函数。但这种做法 的弊端是,在每个可能退出的地方都写上一大堆相同的代码。另外一种方式就是让程序中所有可能退出的点,都全部集中在一个地方处理。这样做的问题是会出现大 量的判断是否成功语句,让代码显得不清晰。Linux提供了下面的两个函数来解决这种问题,把所有的清理函数注册进lib库中,当任意一处调用 exit()时,系统会自动的调用注册上的清理函数。

    int atexit(void (*func)(void))

    注意点:

    1.可以注册多个函数,并且一个函数也可多次注册。当要调用它们时,是按照FILO顺序执行的。

    2.函数注册后,没办法取消注册。

    3.清理函数中调用exit()的行为,在SUSv3中没有定义。在linux中,会继续执行剩下的清理函数。但在某些系统中,可能出现死循环。

    4.子进程会继承父进程中的清理函数。

    #define _BSD_SOURCE

    int on_exit(void (*func)(int, void *), void *arg)

    注意点:

    1. on_exit()是atexit()的改良版。在on_exit()中,可以通过func中的int参数知道exit()的退出状态;同一个func可以根据arg的不同,执行不同的代码。

    2.唯一的缺点是并不是每个系统都实行了改函数。

    代码分析

    int main(int argc, char *argv[])

    {

    printf(“Hello world\n”);

    Write(STDOUT_FILENO, “CC\n”, 3);

    if (fork() == -1)

    exit(1);

    exit(0);

    }

    当在终端执行该程序时,输出入下:

    Hello World

    CC

    当把文字输出到文件时,文件中保存的文字如下:

    CC

    Hello World

    Hello World

    分析:当把文字输出到终端时,stdio函数组是按行输出。而输出到文件时,是按照块输出。也就是说,在输出到文件时,printf()函数 把”Hello World\n”输入进用户stdio缓冲区,但是没有达到输出块的大小。write函数直接把“CC\n”输出到内核缓冲区,而不是用户进程的缓冲区。 接下来fork()出一个子进程,子进程的用户缓冲区是拷贝父进程的,也就是说在子进程中的stdio缓冲区中也存在一个”Hello World\n”,但是内核缓冲区是不会拷贝的。CC出现在Hello World前面是因为执行完write()后,CC已近在内核缓冲区中,而printf()后“Hello World”还在用户stdio缓冲区中,直到执行了exit(),才把“Hello World”刷新到内核缓冲区中。

原文链接: http://linux./soft...

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多