10

我想在它自己的进程组中启动一个进程(或者,一旦启动就改变它的组)并且:

  • 让组中的进程从终端响应Ctrl+C
  • 获取进程组的 id,以便我可以通过kill命令终止组中的所有进程。

注意:我尝试过setsid prog [args],但进程没有从终端响应 Ctrl+C,也无法获得新的进程组 ID。

我还尝试通过 Perl 的setpgrp($pid, $pid)and更改进程组POSIX::setpgid($pid, $pid),但无济于事。

编辑:更大的问题:

我有一个进程(单线程;我们称其为“多产”进程P),它同步启动许多子进程(一个接一个;当前一个子进程终止时,它会启动一个新进程)。从终端,我希望能够杀死P它下面的进程树。为此,我可以简单地安排杀死P's 组中的进程。但是,默认行为是P在其父进程的组中。这意味着P如果我杀死P' 组中的所有进程,则 ' 的父级将被杀死,除非我有P并且它的树在他们自己的组中。

我的意图是杀死P它下面的树,而不是P' 的父母。另外,我不能修改P's 代码本身。

4

3 回答 3

5

你是什​​么意思“在自己的进程组中启动一个进程”?shell 在它们自己的进程组中启动进程,这就是它进行作业控制的方式(通过为前台进程设置一个进程组,为在后台启动的每个管道设置多个进程组)。

要查看 shell 为每个管道启动一个新进程组,您可以执行以下操作:

ps fax -o pid,pgid,cmd | less

这将显示如下内容:

11816 11816  |   \_ /bin/bash
4759   4759  |       \_ ps fax -o pid,pgid,cmd
4760   4759  |       \_ less

请注意,shell 已经为管道创建了一个新的进程组,并且管道中的每个进程都共享该进程组。

编辑:

我想我知道你在说什么。你是system从 Perl 打来的。显然,sh -c不会创建新的进程组,因为它是一个没有作业控制的外壳。

我会做的是fork,然后在孩子身上:

setpgrp;
system("ps fax -o pid,pgid,cmd");

wait在父母身上。

于 2011-04-27T20:16:05.103 回答
1

编辑:如果您想做的是使用 setsid 但找到结果进程的会话 id 和/或 pid:

如果您通过 setsid 命令启动一个进程,它将不会连接到您的终端,所以它当然不会响应 ctrl-c。

您可以通过 grepping 的输出找到它

ps x -O sid 

或者更有限的东西,比如

ps x -o %c,%p,sid

或者通过 proc/[pid]/stat 简单地查看所有条目并查看会话 id 和其他任何感兴趣的内容(有关详细信息,请参阅 man proc)

setsid 的手册页没有提供任何标志来直接生成输出,但您可以通过修改标准轻松制作自己的版本来打印所需的信息。

例如,从其中一个结果中获取 setsid.c 的副本

http://www.google.com/codesearch?as_q=setsid&as_package=util-linux

注释掉 nls 包括,语言环境的东西和 _("") 错误宏,这会导致问题,然后在 execvp 行之前添加它:

    printf("process will be pid %d sid %d\n", getpid(), getsid(0));
于 2011-04-27T19:19:55.713 回答
1

以下是 ninjalj 上述建议后的 Perl 代码中的答案:

prolific_wrapper.pl

my $pid = fork();
if (not defined $pid) {

    die 'resources not available';

} elsif ($pid == 0) {

    # CHILD
    setpgrp;
    exit system(prolific => @ARGV);

} else {

    # PARENT
    my $was_killed = 0;
    local $SIG{INT} = sub {
        say 'kill prolific and its tree ...';
        kill KILL => -$pid;
        $was_killed = 1;
    };
    wait;
    my $child_status = $?;
    $SIG{INT} = 'DEFAULT';
    if ($was_killed) {kill INT => $$}
    else {exit $child_status}

}

再次感谢!

于 2011-04-28T19:01:21.600 回答