进程组中的进程是否应该在Unix/Linux中与其父进程一起终止? [英] Should processes in process group terminate together with their parent in Unix/Linux?

查看:72
本文介绍了进程组中的进程是否应该在Unix/Linux中与其父进程一起终止?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到一个父进程可能产生许多子进程的情况. 我想要实现的是,如果父进程被杀死或退出,那么它的所有子进程都应与父进程一起终止.

I have situation where one parent process may spawn many child processes. What I want to achieve is that if parent process is killed or if it exits, then all it's children should terminate together with parent.

在帖子(下面的链接)中,我发现了建议通过将父流程作为组长来存档. 如果我理解正确的话,这也是流程组的主要目的.我说的对吗?
帖子还提到了prctl(PR_SET_PDEATHSIG,SIGHUP);和其他一些方法,但是它们是特定于以太操作系统的,否则就不会如此完美.

In the post (link below) I have found suggestion to archive this by making parent process a group leader. If I understand it right this is also the main purpose of process groups. Am I right?
Post also mentions prctl(PR_SET_PDEATHSIG, SIGHUP); and some other methods, but they are ether OS specific or otherwise don't seam so elegant.

我编写了一个小示例,试图更好地理解事物,但是它并没有达到我期望的方式.我在做什么错了?

I have written a small demo to try to understand things better, but it doesn't work the way I expect. What am I doing wrong?

//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);
}

此帖子涉及以下方面的建议: * 如何在父级退出后使子进程死亡?

This post relates to suggestion made in : * How to make child process die after parent exits?

推荐答案

请注意,仅在非常有限的情况下,才会将信号发送到子进程. POSIX 说:

Note that a signal is sent to child processes only in a very limited set of circumstances. POSIX says:

  • 如果该进程是控制进程,则将SIGHUP信号发送到属于呼叫进程的控制终端的前台进程组中的每个进程.

  • If the process is a controlling process, the SIGHUP signal shall be sent to each process in the foreground process group of the controlling terminal belonging to the calling process.

如果该过程是控制过程,则与该会话关联的控制终端应与该会话解除关联,以使其可以通过新的控制过程获取.

If the process is a controlling process, the controlling terminal associated with the session shall be disassociated from the session, allowing it to be acquired by a new controlling process.

如果进程的退出导致进程组成为孤立进程,并且如果新孤立的进程组的任何成员都停止了,则应将SIGHUP信号和SIGCONT信号发送给以下位置的每个进程:新近孤立的进程组.

If the exit of the process causes a process group to become orphaned, and if any member of the newly-orphaned process group is stopped, then a SIGHUP signal followed by a SIGCONT signal shall be sent to each process in the newly-orphaned process group.

控制过程的定义是:

The definition of controlling process is:

建立与控制终端的连接的会话负责人.如果该终端随后不再是此会话的控制终端,则会话负责人也将不再是该控制过程.

The session leader that established the connection to the controlling terminal. If the terminal subsequently ceases to be a controlling terminal for this session, the session leader ceases to be the controlling process.

通常,您的进程不会成为建立与控制终端(通常是您的Shell)的连接的会话负责人.

In general, your process is not going to be the session leader that established the connection to the controlling terminal (that will normally be your shell).

如果还有POSIX的另一部分适用,请通知我.

If there's another part of POSIX that applies, please inform me.

我对您的代码(termkids.c)进行了修改,进行了一些测试:

I did some testing with this adaptation of your code (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是在父进程完成后几分钟发送的.

Note that the kill 17702 was sent some minutes after the parent process completed.

这篇关于进程组中的进程是否应该在Unix/Linux中与其父进程一起终止?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆