先看下"_exit"和"exit":
exit被调用时,将冲刷所有的标准I/O流,关闭所有打开的文件描述符。在传统实现中,同时也将关闭标准I/O流。即表示标准输出FILE对象的相关存储区将被清0。而_exit不会执行这些操作。
由于父子进程共享同一地址空间,当父进程恢复运行并调用printf时,不会产生任何输出,它返回-1。这就是上一节调用_exit的原因。
然而,大多数exit的现代实现不再关闭流。因为进程即将终止,内核将关闭所有已打开的文件描述符。
Linux程序的终止分为"正常终止"和"异常终止",具体可能情况如下:
正常终止
- 从main返回
- 调用exit:ISO C定义
- 调用_exit或_Exit:前者由ISO C定义,后者由POSIX.1定义
- 最后一个线程从其启动例程返回
- 最后一个线程调用pthread_exit
异常终止
- 调用abort:产生SIGABRT信号
- 接到某些信号
- 最后一个线程对取消请求做出响应
几个要点:
1.不管进程如何终止,最后都会执行内核中的同一段代码:为相应进程关闭所有打开描述符,释放内存等等。
2.若父进程在子进程之前终止了,则子进程的父进程将变为init进程,其PID为1;保证每个进程都有父进程。
3.当子进程先终止,父进程如何知道子进程的终止状态?事实上,内核为每个终止子进程保存了终止状态等信息,父进程调用wait等函数,就可获取该信息。
4.当父进程调用wait等函数后,内核将释放终止进程所使用的所有内存,关闭其打开的所有文件。
5.对于已经终止、但是其父进程尚未对其调用wait等函数的进程,被称为僵尸进程(即已经结束,但尚未释放资源的)。
6.对于父进程先终止,而被init领养的进程会是僵尸进程吗?init对每个终止的子进程,都会调用wait函数,获取其终止状态信息。
综上所述,子进程调用exit后,父进程必须调用wait。
来源:https://www.cnblogs.com/lq0729/archive/2011/10/24/2222701.html