孤兒進程和殭屍進程

1、定義:什麼是孤兒進程和殭屍進程編程

殭屍進程:一個子進程在其父進程尚未調用wait()或waitpid()的狀況下退出。這個子進程就是殭屍進程。服務器

孤兒進程:一個父進程退出,而它的一個或多個子進程還在運行,那麼那些子進程將成爲孤兒進程。孤兒進程將被init進程(進程號爲1)所收養,並由init進程對它們完成狀態收集工做。併發

殭屍進程將會致使資源浪費,而孤兒則不會。函數

子進程持續10秒鐘的殭屍狀態(EXIT_ZOMBIE)
------------------------------------------------------
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>性能

main()
{
    pid_t pid;
    pid = fork();
    if(pid < 0)
        printf("error occurred!/n");
    else if(pid == 0) {
        printf("Hi father! I'm a ZOMBIE/n");
        exit(0);      //(1)
    }
    else {
        sleep(10);
        wait(NULL);   //(2)
    }
}spa

(1) 向父進程發送SIGCHILD信號
(2) 父進程處理SIGCHILD信號
unix

執行exit(0)時根據其父進程的狀態決定本身的狀態:
    若是父進程已經退出(沒有wait),則該子進程將會成爲孤兒進程過繼給init進程
    若是其父進程尚未退出,也沒有wait(),那麼該進程將向父進程發送SIGCHILD信號,進入殭屍狀態等待父進程爲其收屍。若是父進程一直沒有執行 wait(),那麼該子進程將會持續處於殭屍狀態,若是父進程到死也沒有執行wait則在死後會將zombie進程過繼給init進程,由init進程來 處理zombie進程,最終仍是會死掉。
進程

 

 

子進程將成爲孤兒進程
------------------------------------------------------
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>資源

main()
{
    pid_t pid;
    pid = fork();
    if(pid < 0)
        printf("error occurred!/n");
    else if(pid == 0) {
        sleep(6);
        printf("I'm a orphan/n");
        exit(0);
    }
    else {
        sleep(1);
        printf("Children Bye!/n");
    }
}get

# ./a.out
Children Bye!
# I'm a orphan
(回車後將會進入#)
#


2、有什麼害處:
殭屍進程會佔用系統資源,若是不少,則會嚴重影響服務器的性能
孤兒進程不會佔用系統資源,最終是由init進程託管,由init進程來釋放它。
處理流程:
只要老爹不等wait(sys/wait.h)兒子,兒子都將成爲孤魂野鬼zombie(zombie),unix中默認老爹老是想看兒子死後的狀態(以便報仇) 
  if   老爹比兒子先再見 
  兒子將被init(id   =   1)收養,最後的結果是zombie兒子完全再見,系統資源釋放 
  else   
      { 
        兒子的zombie將一直存在,系統資源佔用... 
        if   老爹dead   
            兒子將被init(id   =   1)收養,最後的結果是zombie兒子完全再見,系統資源釋放 
  
      else   相似的兒子zombie愈來愈多,系統就等死了!!! 
    } 

 

 

signal(SIGCHLD, SIG_IGN); //忽略SIGCHLD信號,這經常使用於併發服務器的性能的一個技巧
                          //由於併發服務器經常fork不少子進程,子進程終結以後須要
                          //服務器進程去wait清理資源。若是將此信號的處理方式設爲
                          //忽略,可以讓內核把殭屍子進程轉交給init進程去處理,省去了
                          //大量殭屍進程佔用系統資源。(Linux Only)

 

3、如何防止殭屍進程
首先明白如何產生殭屍進程:
一、子進程結束後向父進程發出SIGCHLD信號,父進程默認忽略了它
二、父進程沒有調用wait()或waitpid()函數來等待子進程的結束
第一種方法:  捕捉SIGCHLD信號,並在信號處理函數裏面調用wait函數
轉貼Richard Steven的Unix Network Programming代碼

int
main(int argc, char **argv)
{
                ...
        Signal(SIGCHLD, sig_chld);
                for(;
                }
                ...
}

void
sig_chld(int signo)
{
        pid_t        pid;
        int        stat;

        while ( (pid = waitpid(-1, &stat, WNOHANG)) >; 0)
                printf("child %d terminated/n", pid);
        return;
}

 

 

第二種方法:兩次fork():轉載
在《Unix 環境高級編程》裏關於這個在8.6節有很是清楚的說明。

實例
回憶一下8 . 5節中有關僵死進程的討論。若是一個進程要f o r k一個子進程,但不要求它等待
子進程終止,也不但願子進程處於僵死狀態直到父進程終止,實現這一要求的訣竅是調用f o r k
兩次。程序8 - 5實現了這一點。
在第二個子進程中調用s l e e p以保證在打印父進程I D時第一個子進程已終止。在f o r k以後,
父、子進程均可繼續執行——咱們沒法預知哪個會先執行。若是不使第二個子進程睡眠,則
在f o r k以後,它可能比其父進程先執行,因而它打印的父進程I D將是建立它的父進程,而不是
i n i t進程(進程ID 1)。

#include        <sys/types.h>
#include        <sys/wait.h>
#include        "ourhdr.h"

int main(void)
{
        pid_t        pid;

        if ( (pid = fork()) < 0)
                err_sys("fork error");
        else if (pid == 0) {                /* first child */
                if ( (pid = fork()) < 0)
                        err_sys("fork error");
                else if (pid > 0)
                        exit(0);        /* parent from second fork == first child */

                /* We're the second child; our parent becomes init as soon
                   as our real parent calls exit() in the statement above.
                   Here's where we'd continue executing, knowing that when
                   we're done, init will reap our status. */

                sleep(2);
                printf("second child, parent pid = %d/n", getppid());
                exit(0);
        }

        if (waitpid(pid, NULL, 0) != pid)        /* wait for first child */
                err_sys("waitpid error");

        /* We're the parent (the original process); we continue executing,
           knowing that we're not the parent of the second child. */

        exit(0); }   //avoid zombie process by forking twice

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息