Linux的僵尸进程处理1
Linux中有两种异常的进程:
1.孤儿进程:应用通过fork进程后,父进程被kill或者exit,该父进程的子进程被1号进程接管。linux内核启动时候回启动0号进程,启动完毕后0号进程就处于空闲状态,所有的进程的父进程都是有1号进程fork出来的。
2.僵尸进程:fork操作出来的父子进程,子进程收到kil -9的操作或者exit的操作,子进程的内存和CPU资源被操作系统回收,但是PCB块还会在内核中。Linux进程的控制是依靠PCB块的,PCB块记录了进程的运行信息,比如时间片,运行时间,内存资源等等。linux内核按照不同的进程状态把进程放到不同的状态的list中,每次内核会遍历这些list执行对应的进程。
如下就是一个简单的例子,设计到了进程间管道通信、信号注册,信号处理。
#include <assert.h> #include <stdio.h> #include <string.h> #include <signal.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #define TDATA 888 void clear_up(int sig) //收到exit或者kill -9的信号,需要处理的事情 { while(1) { pid_t p = wait(NULL); if(p == -1) break; fprintf(stdout,"******recyle %d ok******\n",p); } } void exit_fuc()//收到sigint的信号的处理 { printf("*********exit %d******\n",getpid()); exit(0); } int main(void) { int fd[2]; //管道处理,两个进程的通信 signal(SIGCHLD,&clear_up); //信号的注册,改信号是发送退出信号给操作系统时候需要处理的事情 signal(SIGINT,&exit_fuc); //信号注册 pid_t pid = -1; if(pipe(fd) == -1) { return -1; } int w_fd = fd[1]; //管道中的fd[1]是写的操作 int r_fd = fd[0];//管道中的fd[0]的是读操作 pid = fork(); //fork一个子进程 assert(pid != -1); if(pid > 0) { close(r_fd); char buf[4] = {'\0'}; int c_sec = 0; while(1) { fprintf(stdout,"I am a parent =%d,my child =%d\n\n",getpid(),getppid()); c_sec++; if(c_sec == 2) { printf("*********send %d********\n",TDATA); //父进程发送消息 memset(buf,'\0',sizeof(int)); sprintf(buf,"%d",TDATA); write(w_fd,buf,sizeof(int));//写到管道 system("ps -ef|grep -v 'grep'|grep 'tx1'"); } sleep(2); } } else { close(w_fd); char buf[4] = {'\0'}; while(1) { fprintf(stdout,"I am a child =%d,my parent =%d\n\n",getpid(),getppid()); system("ps -ef|grep -v 'grep'|grep 'tx1'"); memset(buf,'\0',4); read(r_fd,buf,sizeof(int)); if(strlen(buf) > 0 && atoi(buf) == TDATA) { fprintf(stdout,"********recive %s***********\n",buf); //如果收到内容 kill(getpid(),9); //给操作系统发送9号信号 } sleep(1); } } return 0; }
运行结果:
zhoulin@:~/code/c/demo:./tx1 I am a parent =39267,my child =7742 I am a child =39268,my parent =39267 zhoulin 39267 7742 0 20:52 pts/1 00:00:00 ./tx1 --父进程 zhoulin 39268 39267 0 20:52 pts/1 00:00:00 ./tx1 --子进程 I am a parent =39267,my child =7742 *********send 888******** 主进程发送内容 ********recive 888*********** 子进程接受内容 zhoulin 39267 7742 0 20:52 pts/1 00:00:00 ./tx1 --父进程 zhoulin 39268 39267 0 20:52 pts/1 00:00:00 [tx1] <defunct> --子进程进行了exit操作,linux内核中的pcb并没有回收 ******recyle 39268 ok****** --主进程监听到了kill 9的信号,进行的wait操作,回收了僵尸进程。 I am a parent =39267,my child =7742 --此时再次打印的就只有父进程了 ^C*********exit 39267****** --Ctrl+c的发送sigint的信号,该信号对应的函数exit_fuc的处理,就是退出父进程