爲什麼孤兒進程沒有被init收養

我們都知道在Linux上孤兒進程和殭屍進程都會被進程號爲1的init進程收養,收屍,但這在使用Systemd來管理系統的發行版上比如Ubuntu上就不是那麼靠譜了

首先我們寫一個簡單的孤兒進程的例子

#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>

int 
main(void)
{
    switch(fork()){
        case 0:
            printf("Child process\n");
            printf("child process: %d\n", getpid());
            printf("father pid:%d\n", getppid());
            sleep(5);
            printf("\nnow pid: %d\t ppid:%d \n",getpid(),getppid());
            break;
        case -1:
            printf("Fork failed");
            exit(-1);
        default:
            printf("Father Process\n");
            sleep(1);
            printf("Father exit\n");
            break;
    }
    return 0;
}

首先我們在圖像界面上僞終端中運行


發現孤兒進程會被進程號爲1391的systemd進程收養,而不是pid爲1的systemd進程


然後我們在終端中運行該例子,發現成功父進程成功變爲1


很顯然問題應該時出在systemd上面,查看源碼可以發現在systemd中調用了prctl()系統調用

systemd源碼src/core/main.c


現在看一下Linux中特有的系統調用prctl( )

#include <sys/prctl.h>        

int prctl(int option, unsigned long arg2, unsigned long arg3,                 

                        unsigned long arg4, unsigned long arg5);

option參數指示prctl如何操作進程

PR_SET_CHILD_SUBREAPER爲內核3.4版本中新增的選項

        第二個參數若爲非零時,調用進程設置'child subreaper'屬性

        第二個參數若爲零則取消該屬性

詳細參數可以查看The Linux man-pages project

孤兒進程成會被祖先中距離最近的supreaper進程收養

現在我們使用自己的進程來收養他後代的孤兒進程

#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<linux/prctl.h>

void descendant_process(void);

int 
main(void)
{
    prctl(PR_SET_CHILD_SUBREAPER,1);
    //設置的child subreaper不會被繼承
    switch(fork()){
        case 0:
            descendant_process();
            break;
        case -1:
            printf("Fork failed");
            exit(-1);
        default:
            printf("Subreaper Process:%d\n",getpid());
            sleep(1);
            for(;;);
    }
    return 0;
}

void
descendant_process(void)
{
    switch(fork()){
        case 0:
            printf("Child process\n");
            printf("child process: %d\n", getpid());
            printf("father pid:%d\n", getppid());
            sleep(5);
            printf("now pid: %d\t ppid:%d \n",getpid(),getppid());
            break;
        case -1:
            printf("Fork failed");
            exit(-1);
        default:
            printf("Father Process\n");
            sleep(1);
            printf("Father exit\n");
            break;
    }    
    return;
}
成功收養~




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