exit()
函数和 _exit()
函数都是用来终止进程的。当程序执行到 exit()
函数或 _exit()
函数时,进程会无条件地停止剩下的所有操作,清除各种数据结构,并终止本进程的运行。但是,这两个函数仍然有一些本质的区别,如下图所示:
从上图可以看出, _exit()
函数的作用是直接使进程停止运行,清除其使用的内存空间,并清除其在内核中的各种数据结构; exit()
函数则在这些基础上做了一些包装,在执行退出之前加了若干道工序。 exit()
函数与 _exit()
函数最大的区别就在于 exit()
函数在终止当前进程之前要检查该进程打开了那些文件,并把文件缓存区中的内容写回文件,即上图所示的“刷新I/O缓存区”。
在 Linux
的标准库函数中,有一种被称为“缓存I/O(buffered I/O)”操作,其特征就是对应每一个打开的文件,在内存中都有一片缓存区。
每次读文件时,会连续读出若干条记录,这样在下次读文件时就可以直接从内存的缓存区中读取;同样,每次写文件的时候,也仅仅时写入内存中的缓存区,等满足了一定的条件(如缓存区满)时,再将缓存区中的内容一次性写入文件。
这种技术大大增加了文件读写的速度,但也给编程带来了一些麻烦。比如有些数据,认为已经被写入文件了,实际上因为没有满足特定的条件,它们还只是保存在缓存区中,这时用 _exit()
函数直接将进程关闭,缓存区中的数据就会丢失。因此,若想保证数据的完整性,最好使用 exit()
函数。
#include <stdlib.h> void exit(int status); #include <unistd.h> void _exit(int status);点击复制复制失败已复制
示例
通过简单的示例,展示两个函数的区别,如下所示:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(int argc, const char *argv[]) { printf("exit before..."); _exit(0); printf("exit after..."); return 0; }点击复制复制失败已复制
编译并运行之后会发现没有任何输出。原因是 printf()
作为标准输出函数,在没有换行符刷新时,执行输出打印到缓存区中,然后调用调用 _exit()
函数,将程序退出,缓存区中的数据就会丢失。
如果将 _exit()
函数换成 exit()
函数,则结果完全不同:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> int main(int argc, const char *argv[]) { printf("exit before..."); exit(0); printf("exit after..."); return 0; }点击复制复制失败已复制
编译并运行:
$ gcc main.c && ./a.out exit before...% 点击复制复制失败已复制
提示
两个代码都没有输出 "exit after..."
,说明两个函数都具有主动调用将进程退出的功能。