exit() 和 _exit() 的区别

exit()和_exit()的效果都是让程序退出执行,而_exit()用来“尽快”退出。

atexit()

先说一下atexit()函数。我们可以用atexit()注册一个或多个函数退出清理函数(或者on_exit()但这个函数不建议用),这些清理函数按照注册时的反顺序,在exit()或main函数return时被调用。

#include <stdlib.h>
int atexit(void (*function)(void)); //return 0 on success.

注意,fork子进程时,这些函数会被继承到子进程。而exec系列执行成功后,所有函数会被清空。

exit()

我们知道父进程要wait子进程的退出状态,在子进程退出到父进程调用wait()期间,子进程就处于僵尸状态。因此,exit()将进程正常退出,并将(status & 0377)返回到父进程的wait(),其中status可以是EXIT_SUCCESS或EXIT_FAILURE。

#include <stdlib.h>
void exit(int status);

exit()在返回到父进程前要做的事情包括:按出栈顺序(反序)依次调用atexit()/on_exit()注册的函数。然后将所有打开的stdio流进行flush并关闭,如果有通过tmpfile()创建的文件也会被删除。(这里要注意,如果你注册的某个清理函数中调用_exit()或把自己kill结果退出了,那么后面的清理函数以及刷stdio等就不会执行了。所以,清理函数里不要调用exit()或_exit()。)

子进程exit()后会发送一个SIGCHLD信号给父进程(如果父进程设置了SA_NOCLDWAIT,那这个信号是否发送是未定义的)。
如果子进程在exit()后,父进程已经在等待(wait()系列函数)子进程的状态,或者父进程设置了SA_NOCLDWAIT或者将SIGCHLD的处理置为SIG_IGN,子进程都会立即退出。而如果父进程既没有wait,又没有设置忽略子进程退出,子进程就会变成僵尸进程(除了一个字节的exit status,什么都没有,用来确保以后某个时刻父进程wait的时候仍能拿到status,来解除子进程的僵尸状态)。如果父进程到死都没有wait,那僵尸进程会被init收养然后用wait清理掉它。

_exit()

而_exit()是企图让程序“立即”退出,它不会调用上述atexit()/on_exit()注册的函数。它也是会关闭自己打开的所有文件描述符的,但是否flush stdio以及是否删除tmpfile创建的文件则是与具体实现相关的(即没有明确规定)。我本地实验的结果是exit()会flush所有打开文件(stdio和其他文件)的缓冲,而_exit()不会。


                
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值