2014-05-13 30 views
4

我有一個父進程可能會產生許多子進程的情況。 我想要實現的是,如果父進程被終止或者它退出,那麼它所有的子進程應該與父進程一起終止。進程組中的進程是否應該在Unix/Linux中與其父進程一起終止?

在帖子中(下面的鏈接)我發現建議通過讓父進程成爲組長來歸檔這個建議。 如果我理解正確,這也是過程組的主要目的。我對嗎?
帖子中還提到了prctl(PR_SET_PDEATHSIG,SIGHUP);和其他一些方法,但它們是以太網操作系統特定的,否則沒有接縫那麼優雅。

我寫了一個小的演示,試圖更好地理解事物,但它並不按我期望的方式工作。我究竟做錯了什麼?

//https://www.andrew.cmu.edu/course/15-310/applications/homework/homework4/terminalgroups1.html 
#include <stdio.h> 
#include <stdlib.h> 
#include <signal.h> 
#include <stddef.h> 
#include <errno.h> 
#include <string.h> 
#include <sys/wait.h> 
#include <sys/ioctl.h> 
#include <sys/termios.h> 

int main() 
{ 
    int status; 
    int cpid; 
    int ppid; 

    ppid = getpid(); 
    printf("parent: %d\n", ppid); 

    if (!(cpid=fork())) 
    { 
     printf("child: %d\n", getpid()); 
     if(setpgid(0,ppid) == -1) 
      printf("child setpgid errno %s\n", strerror(errno)); 
     else 
      printf("child gid %d\n", getpgid(0)); 
     pause(); 
     printf("child exited\n"); 
     exit (-1); 
    } 

    if (cpid < 0) 
     exit(-1); 

    setpgid(0, ppid); 
    if(setpgid(0,0) == -1) 
     printf("parent setpgid erno %s\n", strerror(errno)); 
    else 
     printf("parrent gid %d\n", getpgid(0)); 


    sleep(7); 
    printf("parent exit\n"); 
    exit(0); 
} 

這篇文章涉及在由建議: * How to make child process die after parent exits?

+0

*如何*它不按您期望的方式工作?你能指望什麼? –

+0

父進程在7秒後終止,但子進程依然存在並且被init進程孤立。我希望孩子能夠收到一些信號,並與父母一起終止。 – user2979375

+0

http://man7.org/linux/man-pages/man3/exit.3.html說,但我不知道這是否是在這種情況下是實際的: 如果該過程是會議的領導者,其控制終端是 該會話的控制終端,則該控制終端的前臺進程組中的每個進程被髮送一個SIGHUP信號,並且該終端與該會話取消關聯,允許它被新的控制進程獲取。 – user2979375

回答

1

可以使用的atexit來註冊發送SIGHUP信號都具有相同的處理組ID的處理的函數。當父母離開時,這將具有向所有孩子發送信號的預期效果。但是請注意,子項中的SIGHUP信號處理程序會導致子項立即退出,而不會從pause()返回並打印子項退出消息。

#include <stdio.h> 
#include <stdlib.h> 
#include <signal.h> 
#include <stddef.h> 
#include <errno.h> 
#include <string.h> 
#include <sys/wait.h> 
#include <sys/ioctl.h> 
#include <sys/termios.h> 
#include <sys/types.h> 

void killall() 
{ 
    kill(0, SIGHUP); 
} 

int main() 
{ 
    int status; 
    int cpid; 
    int ppid; 

    if (atexit(killall) != 0) 
    { 
     fprintf(stderr, "atexit failed with %d", errno); 
     exit(-1); 
    } 

    ppid = getpid(); 
    printf("parent: %d\n", ppid); 

    if (!(cpid=fork())) 
    { 
     printf("child: %d\n", getpid()); 
     if(setpgid(0,ppid) == -1) 
      printf("child setpgid errno %s\n", strerror(errno)); 
     else 
      printf("child gid %d\n", getpgid(0)); 
     pause(); 
     printf("child exited\n"); 
     exit (-1); 
    } 

    if (cpid < 0) 
     exit(-1); 

    setpgid(0, ppid); 
    if(setpgid(0,0) == -1) 
     printf("parent setpgid erno %s\n", strerror(errno)); 
    else 
     printf("parent gid %d\n", getpgid(0)); 


    sleep(7); 
    printf("parent exit\n"); 
    exit(0); 
} 
3

請注意,信號僅在非常有限的一些情況下發送給子進程。 POSIX說:

  • 如果該過程的控制過程中,SIGHUP信號應屬於調用進程的控制終端的前臺進程組中被髮送到每一個過程。

  • 如果該過程是一個控制過程,與該會話相關聯的控制終端應與會話分離,從而允許通過新的控制過程獲取該會話。

  • 如果進程退出導致進程組成爲孤立進程,並且新孤立進程組的任何成員停止,那麼SIGHUP信號後跟SIGCONT信號應發送給進程組中的每個進程新孤兒進程組。

controlling process的定義是:

所建立到控制終端連接的會話領導者。如果終端隨後不再成爲本次會議的控制終端,則會議領導者不再是控制過程。

一般而言,您的流程不會是與控制終端建立連接的會話負責人(通常是您的shell)。

如果還有POSIX的另一部分適用,請通知我。

我做了一些測試與此相適應你的代碼(termkids.c)的:

#include "posixver.h" 
#include <errno.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 
#include <signal.h> 

static void sigcatcher(int signum) 
{ 

    printf("%d: Signal caught: %d\n", (int)getpid(), signum); 
    exit(1); 
} 

int main(void) 
{ 
    int cpid; 
    int ppid; 

    ppid = getpid(); 
    printf("Parent PID: %d\n", ppid); 
    printf("Initial PGID: %d\n", (int)getpgid(0)); 
    if (setpgid(0, 0) != 0) 
    { 
     fprintf(stderr, "setpgid() failed (%d: %s)\n", errno, strerror(errno)); 
     return 1; 
    } 
    printf("Revised PGID: %d\n", (int)getpgid(0)); 

    if ((cpid=fork()) < 0) 
    { 
     fprintf(stderr, "fork() failed (%d: %s)\n", errno, strerror(errno)); 
     return 1; 
    } 
    else if (cpid == 0) 
    { 
     cpid = getpid(); 
     printf("Child PID: %d\n", cpid); 
     printf("Child PGID: %d\n", (int)getpgid(0)); 
     (void)signal(SIGTERM, sigcatcher); 
     (void)signal(SIGHUP, sigcatcher); 

     pause(); 
     printf("%d: child exited\n", cpid); 
     return(-1); 
    } 

    printf("Parent - sleeping\n"); 
    sleep(7); 
    printf("Parent exits\n"); 
    return(0); 
} 

輸出示例:

$ ./termkids 
Parent PID: 17701 
Initial PGID: 17701 
Revised PGID: 17701 
Parent - sleeping 
Child PID: 17702 
Child PGID: 17701 
Parent exits 
$ ps 
    PID TTY   TIME CMD 
    388 pts/5 00:00:00 bash 
17702 pts/5 00:00:00 termkids 
17707 pts/5 00:00:00 ps 
$ kill 17702 
17702: Signal caught: 15 
$ 

注意,kill 17702被送到幾分鐘父進程完成之後。

相關問題