【原创】《Linux高级程序设计》杨宗德著 - 进程管理与程序开发 - 回收进程用户/内核资源
【原创】《Linux高级程序设计》杨宗德著 - 进程管理与程序开发 - 回收进程用户/内核资源
1. 回收进程用户空间资源
在Linux系统下,可以通过一下方式结束进程:
1. 显示调用exit或_exit系统调用;
2. 在main函数中执行return语句;
3. 隐含地离开main函数,例如遇到main函数的""}.
exit和return的区别,看代码运行结果:
/************************************************************************* > File Name: exit_return.c > Author: Geng > Mail: genglut@163.com > Created Time: Sat 01 Nov 2014 09:59:56 PM CST ************************************************************************/ #include<stdio.h> #include<unistd.h> #include<stdlib.h> int test(void) { printf("a\n"); sleep(1); exit(0); //return 0; } int main(void) { int i; i++; printf("i = %d\n", i); while(1) test(); return 0; }
函数test中使用exit(0)时运行结果:
$ ./a.out i = -1217134603 a
函数test中使用return时运行结果:
$ ./a.out i = -1217400843 a a a ^C
从运行结果可以看出,在子函数test中,若使用exit(0),则循环只执行一次;如果使用return关键字,则一直处于死循环。
即:1. return退出当前函数,exit()退出当前进程。2. return仅从子函数中返回,并不退出进程,调用exit()时要调用一段终止处理程序,然后关闭所有I/O流。
_exit(int status)函数把参数status返回给父进程而直接退出,此函数调用后不返回,而是传递SIGCHLD信号给父进程,父进程可以通过wait函数获得子进程的结束状态,_exit不会处理标准I/O缓冲区,如果需要更新需要调用exit()。
示例代码:
/************************************************************************* > File Name: _exit_example.c > Author: Geng > Mail: genglut@163.com > Created Time: Sat 01 Nov 2014 10:17:51 PM CST ************************************************************************/ #include<stdio.h> #include<stdlib.h> #include<unistd.h> int main(void) { printf("output\n"); printf("content in buffer");//后面不能有回车 _exit(0);//只输出output,没有清理缓冲区 //exit(0);//改为此句将输出 output和content in buffer }
注册退出处理函数atexit()和on_exit()
它们用来注册在执行exit函数前执行的操作函数,其实现使用了回调函数的方法。两函数的功能是告诉进程,在正常退出时执行注册的func函数,差异仅是atexit注册的函数没有参数。
示例代码:
/************************************************************************* > File Name: on_exit_example.c > Author: Geng > Mail: genglut@163.com > Created Time: Sat 01 Nov 2014 10:26:27 PM CST ************************************************************************/ #include<stdio.h> #include<stdlib.h> void test_exit(int status, void *arg) { printf("before exit()!\n"); printf("exit %d\n", status); printf("arg = %s\n", (char *)arg); } int main() { char *str = "test"; on_exit(test_exit, (void *)str); exit(4321); }
运行结果:
$ ./a.out before exit()! exit 4321 arg = test
2. 回收进程内核空间资源
上面介绍进程退出时释放了用户空间资源,但是,进程PCB并没有释放,这一工作显然不是有自己完成,而是由当前进程的父进程通过显示调用那个wait和waitpid函数来完成。
调用wait函数的父进程将阻塞式等待进程中任意一个子进程结束后,回收该子进程的内核进程资源。
示例程序:
#include<stdio.h> #include<sys/wait.h> #include<sys/types.h> #include<unistd.h> #include<sys/errno.h> #include<stdlib.h> extern int errno; int main(int argc,char *argv[]) { pid_t pid_one,pid_wait; int status; if((pid_one=fork())==-1) perror("fork"); if(pid_one==0) { printf("my pid is %d\n",getpid()); sleep(1); exit(EXIT_SUCCESS); } else { pid_wait=wait(&status); if(WIFEXITED(status)) printf("wait on pid:%d,return value is:%4x\n",pid_wait,WEXITSTATUS(status)); else if(WIFSIGNALED(status)) printf("wait on pid:%d,return value is:%4x\n",pid_wait,WIFSIGNALED(status)); } return 0; }
运行结果:
$ ./a.out my pid is 8199 wait on pid:8199,return value is: 0