linux下避免殭屍進程的幾種方法

    linux下我們可以調用fork函數創建子進程,創建的子進程將會得到父進程的數據空間、堆、棧......副本(採用寫時複製機制),子進程將會繼承父進程的信號掩碼、信號處理方式、當前工作目錄、會話id、組id......。當子進程退出時父進程應當及時獲取子進程退出狀態,否則,如果父進程是一直在運行,那麼子進程的退出狀態將一直保存在內存中,直到父進程退出才釋放。

我們可以使用如下幾種方法避免殭屍進程的產生:
    1.在fork後調用wait/waitpid函數取得子進程退出狀態。

    2.調用fork兩次(第一次調用產生一個子進程,第二次調用fork是在第一個子進
      程中調用,同時將父進程退出(第一個子進程退出),此時的第二個子進程的父
      進程id爲init進程id(注意:新版本Ubuntu並不是init的進程id))。

    3.在程序中顯示忽略SIGCHLD信號(子進程退出時會產生一個SIGCHLD信號,我
      們顯示忽略此信號即可)。

    4.捕獲SIGCHLD信號並在捕獲程序中調用wait/waitpid函數。
方法一:

#include "../common/common.h"

int main(void)
{
    pid_t pid;

    if ((pid = fork()) < 0) {
        perror("fork error");
        return EXIT_FAILURE;
    } else if (0 == pid) {
        printf("[%ld] child process is running...\n", (long)getpid());
        _exit(0);
    }

    //sleep(15);

    if (waitpid(pid, NULL, 0) < 0) {
        perror("waitpid error");
        return EXIT_FAILURE;
    }

    for (; ;) {
        pause();
    }
    return EXIT_SUCCESS;
}
方法二:

#include <sys/wait.h>

#include "../common/common.h"

int main(void)
{
    pid_t pid;

    if ((pid = fork()) < 0) {
        perror("fork error");
        return EXIT_FAILURE;
    } else if (0 == pid) {
        printf("first child is running..\n"); 
        /**在第一個子進程中再次fork***/
        if ((pid = fork()) < 0) {
            perror("fork error");
            return EXIT_FAILURE;
        } else if (pid > 0) {/**父進程退出**/
            printf("[%ld] first child is exit...\n", (long)getpid());
            _exit(0);
        }

        sleep(2);/**確保父進程先運行**/
        printf("second process pid: %ld, second process's parent pid: %ld\n", (long)getpid(), (long)getppid()); 
        //sleep(15);
        printf("[%ld] is exit..\n", (long)getpid());
        _exit(0);
    }

    /***獲得第一個子進程的退出狀態***/
    if (waitpid(pid, NULL, 0) < 0) {
        perror("waitpid error");
        return EXIT_FAILURE;
    }

    for(;;)
        pause();

    return EXIT_SUCCESS;
}
方法三:

#include <signal.h>

#include "../common/common.h"

int main(void)
{
    /***顯示忽略SIGCHLD信號****/
    if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) {
        perror("signal error");
        return EXIT_SUCCESS;
    }


    pid_t pid;
    int i;
    /**產生10個子進程***/
    for (i=0; i<10; ++i) {
        if ((pid = fork()) < 0) {
            perror("fork error");
            return EXIT_FAILURE;
        } else if (0 == pid) {
            _exit(0);
        }

        sleep(2);
        continue;
    }


    for (; ;)
        pause();

    return EXIT_SUCCESS;
}
方法四:

#include <signal.h>
#include <sys/wait.h>

#include "../common/common.h"


void sig_chld(int signo);

int main(void)
{
    /**捕獲此信號, 此刻系統會立刻檢測是否有次信號產生**/
    if (signal(SIGCHLD, sig_chld) == SIG_ERR) {
        handler_err("signal error to SIGCHLD");
    }

    pid_t pid;
    int i;


    for (i=0; i<10; i++) {

        if ((pid = fork()) < 0) {
            handler_err("fork error");
        } else if (0 == pid) {
            printf("child pid: %d\n", getpid());
            _exit(0);
        } 

        sleep(1);
        continue;
    }

    for (; ;) {
        pause();
    }   
    return EXIT_SUCCESS;
}

/**捕獲到信號後會立刻執行此段代碼***/
void sig_chld(int signo)
{
    printf("receive child signal\n");


    if (waitpid(-1, NULL, 0) < 0) {
        perror("waitpid error");
    }

    if (signal(SIGCHLD, sig_chld) == SIG_ERR) {
        perror("signal error to SIGCHLD");
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章