Linux 结束进程
一个进程由于以下5个原因中的一个终止 --main函数调用return; --调用exit函数--C语言库函数; --调用_exit函数--系统调用 --调用abort函数 --被一个信号终止。(kill函数) 前三个原因都是正常终止,后面两个是非正常终止。 无论进程为何终止,最后都执行相同的内核代码代码,关闭打开的文件,释放内存资源,和其他清理工作。
exit函数 int exit(int status); exit导致程序正常终止,并且返回给父进程的状态(status) exit的参数便是返回给父进程的状态码 在main函数中调用return和exit效果类似,但是在子函数中,return是退出当前函数,exit却是退出当前进程
exit()是C语言库函数,_exit()是系统调用,
exit在退出程序时,先调用终止处理程序,然后清除I/O缓冲,然后再调用系统调用_exit(),所以exit()可以打印出printf()函数中的字符串;
_exit()会直接进入到Linux内核操作,不会清除I/O缓冲
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> int main(int arg,char *args[]) { /*Linux下,printf函数必须以'\n'结尾才会立刻输出到屏幕, * 如果没有'\n'直到输出缓冲区满了以后才会打印到屏幕上(敲击换行也算)*/ printf("hello world!"); //exit(0); 打印 "hello world!" _exit(0); //不打印 "hello world!" }
exit()会调用终止处理程序 atexit()可以注册终止处理程序,ANSIC规定最多可以注册32个终止处理程序 终止处理程序的调用与注册次序相反 int atexit(void (*function)(void));
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> void by1(void) { printf("by1 执行了!\n"); } void by2(void) { printf("by2 执行了!\n"); } int main(int arg,char *args[]) { //注册终止处理程序 atexit(by1); atexit(by2); printf("hello world!\n"); exit(0); //_exit(0); _exit()不执行终止处理程序 /* * 打印: * hello world! * by2 执行了! * by1 执行了! * 证明了先注册后执行 * */ }
abort函数 void abort(void); abort导致程序异常终止 abort还可以让程序产生core,这是大多数调试器用户分析程序崩溃时的文件。 虽然任何打开的文件都被关闭了,但是abort仍然是个粗暴的调用,应该作为最后的手段来使用。 比如当你遇到一个很严重内存不足这样的错误,无法用程序的方式处理时再使用。
kill函数 int kill(pid_t pid,int sig); exit,abort用来杀死进程自己。 kill函数用来杀死另一个进程。 参数pid指定一个要杀死的进程,而sig是要发送的新号,本章内容是杀死一个进程,所以只需要关注SIGKILL一个信号。 例如:kill(2056,SIGKILL);