Linux系统编程——僵尸的模拟以及僵尸进程的预防
僵尸進(jìn)程介紹
子進(jìn)程終止,父進(jìn)程尚未回收,子進(jìn)程殘留資源(PCB)存放于內(nèi)核中,變成僵尸進(jìn)程。由于我們的程序也許是7*24小時(shí)不宕機(jī)的,程序不結(jié)束,僵尸進(jìn)程殘留在PCB中資源就不會(huì)被回收,所以我們要清晰的認(rèn)識(shí)僵尸進(jìn)程,在程序中盡量避免僵尸進(jìn)程。
僵尸進(jìn)程模擬
我們通過(guò)下面程序來(lái)進(jìn)行模擬僵尸進(jìn)程,父進(jìn)程fork()5個(gè)子進(jìn)程,最后一個(gè)子進(jìn)程用于查看僵尸進(jìn)程,讓父進(jìn)程最后死亡。
代碼展示
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <error.h> #include <sys/errno.h>void perr(const char* str) {perror(str);exit(1); } int main(int argc,char* argv[]) {pid_t pid;int i;for( i = 0; i < 5;i++ ){if( (pid = fork()) == 0 ){break; //子進(jìn)程}else if (pid < 0){perr("fork error"); }}if( i < 4 ) //子進(jìn)程0,1,2,3 最先死亡 模擬僵尸進(jìn)程{printf("i am child process,pid = %d,ppid = %d.i am died.\n",getpid(),getppid());exit(1);}else if( i==4 ) //子進(jìn)程4 顯示僵尸進(jìn)程{sleep(1);printf("i am child process[exec ps],pid = %d,ppid = %d.\n",getpid(),getppid());execlp("ps","ps","j",NULL);}else //父進(jìn)程活3秒 查看僵尸進(jìn)程現(xiàn)象 {printf("i am parent process,pid = %d,ppid = %d.i will die after 3s.\n",getpid(),getppid());sleep(3);}return 0; }僵尸進(jìn)程現(xiàn)象
僵尸進(jìn)程預(yù)防
如何預(yù)防僵尸進(jìn)程呢?可能很多人都知道,子進(jìn)程死亡了父進(jìn)程回收資源唄。對(duì),只要子進(jìn)程死亡了,父進(jìn)程負(fù)責(zé)收尸就行了。 
 這里有2種方式回收子進(jìn)程資源。如下: 
 - 父進(jìn)程在死亡之前輪詢(xún)的去查看子進(jìn)程是否死亡,死亡了就回收,主要使用wait/waitpid  
 - 父進(jìn)程由自己的事情做,子進(jìn)程死亡了通知父進(jìn)程收尸,主要使用信號(hào)回調(diào)signal/sigaction 
 這里最好的方式當(dāng)然是采用信號(hào)唄,有子進(jìn)程死亡,父進(jìn)程才進(jìn)行回收!
代碼展示
代碼中要注意的是,子進(jìn)程可能同時(shí)終止,同時(shí)發(fā)送信號(hào),父進(jìn)程執(zhí)行信號(hào)回調(diào)函數(shù)但是默認(rèn)只處理1個(gè),所以要用while進(jìn)行回收! while( (wpid = waitpid(-1,NULL,WNOHANG)) != -1 );
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <error.h> #include <sys/errno.h> #include <signal.h> #include <wait.h>void perr(const char* str) {perror(str);exit(1); } void wait_child(int signo) {pid_t wpid;//子進(jìn)程可能同時(shí)終止,同時(shí)發(fā)送信號(hào)到這里來(lái)默認(rèn)只處理1個(gè),所以要用while!while( (wpid = waitpid(-1,NULL,WNOHANG)) != -1 );waitpid(-1,NULL,0); } int main(int argc,char* argv[]) {pid_t pid;int i;struct sigaction act;act.sa_flags = 0;act.sa_handler = wait_child; sigemptyset(&act.sa_mask);sigaction(SIGCHLD,&act,NULL);for( i = 0; i < 5;i++ ){if( (pid = fork()) == 0 ){break; //子進(jìn)程}else if (pid < 0){perr("fork error"); }}if( i < 4 ) //子進(jìn)程0,1,2,3 最先死亡 模擬僵尸進(jìn)程{printf("i am child process,pid = %d,ppid = %d.i am died.\n",getpid(),getppid());exit(1);}else if( i==4 ) //子進(jìn)程4 顯示僵尸進(jìn)程{sleep(1); printf("i am child process[exec ps],pid = %d,ppid = %d.\n",getpid(),getppid());execlp("ps","ps","j",NULL);}else //父進(jìn)程活3秒 查看僵尸進(jìn)程現(xiàn)象{printf("i am parent process,pid = %d,ppid = %d.i will die after 3s.\n",getpid(),getppid());sleep(3);}return 0; }查看預(yù)防效果
總結(jié)
以上是生活随笔為你收集整理的Linux系统编程——僵尸的模拟以及僵尸进程的预防的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
 
                            
                        - 上一篇: python (高级消息队列)普通、进程
- 下一篇: 树:二叉树的层序遍历算法(超简洁实现及详
