一.简介
SYNOPSIS
#include <stdlib.h>
void exit(int status);
#include <unistd.h>
void _exit(int status);
#include estdlib.h>
void _Exit (int status);
二.进程退出
正常退出
- main函数调用return
- 进程调用exit(),标准c库
- 进程调用_exit()或者_Exit(),属于系统调用
补充:
- 进程最后一个线程返回
- 最后一个线程调用pthread_exit
异常退出
- 调用abort
- 当进程收到某些信号时,如ctrl+C
- 最后一个线程对取消(cancellation)请求做出响应
不管是哪一种退出方式,最后都会执行内核中的同一代码,这段代码用来关闭进程所用到的已经打开的文件描述符所占用的内存和资源.
exit和_exit函数说明
创建进程使用fork()函数,执行进程使用exec函数族,终止进程则使用_exit()和exit()函数. 当进程执行到exit()或_exit()函数时
,进程会无条件的 停 止剩下的所有操作,清楚各种数据结构,并终止本进程的运行. 但是,这两个函数还是有区别的.
他们的调用过程如下:
从图里可以看出来,_exit()函数的作用是: 直接使进程停止运行,清除其使用的内存空间,并清除其在内核中的各种数据结构; 而exit()函数则在这 些基础上做了一些包装,在执行退出之前加了若干道工序. exit()函数和_exit()函数的最大区别就在于exit()函数在终止当前进程之前要检查该进程 打开过那些文件,把文件缓冲区中的内容写回文件,也就是图中的 “清楚I/O缓冲” 一项.
在Linux的标准函数库中,有一种被称为 “缓冲I/O” 的操作,其特征就是对应每一个打开的文件,在内存中都有一片缓冲区. 每次读文件时,会联系读 出若干条记录,这样在下次读文件时就可以直接从内存的缓冲区当中读取; 同样的,每次写文件的时候,也仅仅是写入内存的 缓冲区,等满足了一定的 条件时(如达到一定数量或遇到特定字符等,最典型的就是咱们的vim中使用的 : w命令),再将缓冲区中的内容一次性写入文 件.
这种技术大大增加了文件读写的速度,但是也给编程带来了一点麻烦. 比如有些数据你认为已经被写入到文件中,实际上因为没有满足特定的条件,他 们还只是被保存在缓冲区内,这时用_exit()函数直接将进程关闭掉,缓冲区中的数据就会丢失. 因此,为了数据的完整性,请使用exit()函数.
代码演示
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
pid_t pid;
int cnt = 0;
pid = vfork();
if(pid > 0){
while(1){
printf("this is father pid, pid = %d\n",getpid());
printf("father cnt = %d\n",cnt);
sleep(3);
}
}else if(pid = 0){
while(1){
printf("this is child pid ,pid = %d\n",getpid());
cnt++;
printf("child cnt = %d\n",cnt);
sleep(3);
if(cnt == 5){
exit(3);
// _exit(3);
// _Exit(3);
}
}
}
return 0;
}