我想你可能对过程组ID的工作方式有些困惑。
首先,我收拾你的源:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
pid_t pid;
void
handler (int signum, siginfo_t * siginfo, void *context)
{
printf ("in signal handler pid is %d, getpgid(pid) is %d \n",
pid, getpgid (pid));
printf
("in signal handler siginfo->si_pid is %d, getpgid(siginfo->si_pid) is %d \n",
siginfo->si_pid, getpgid (siginfo->si_pid));
exit (0);
}
int
main (int argc, char **argv)
{
struct sigaction sa;
memset (&sa, 0, sizeof (sa));
sa.sa_sigaction = handler;
sigemptyset (&sa.sa_mask);
sa.sa_flags = SA_RESTART | SA_SIGINFO;
sigaction (SIGINT, &sa, NULL);
pid = getpid();
printf ("before call pgid is %d pid=%d\n", getpgid (pid), pid);
setpgid (pid, pid);
printf ("after setpgid call pgid is %d pid=%d\n", getpgid (pid), pid);
tcsetpgrp (STDIN_FILENO, pid);
printf ("after tcsetprgrp call pgid is %d pid=%d\n", getpgid (pid), pid);
while (1)
{
}
}
主要的变化是,如果您的处理程序有三个参数,你需要使用SA_SIGINFO
和sa_sigaction
不sa_handler
指定处理。没有这个,你的处理程序可能会变得无效的第二和第三个参数。
接下来,我修复了您的处理程序,以便打印出si_pid
以及pid
。
我也进行了一些额外的调试。
这是当我从外壳直跑会发生什么:
$ ./x
before call pgid is 15136 pid=15136
after setpgid call pgid is 15136 pid=15136
after tcsetprgrp call pgid is 15136 pid=15136
^Cin signal handler pid is 15136, getpgid(pid) is 15136
in signal handler siginfo->si_pid is 0, getpgid(siginfo->si_pid) is 15136
注意siginfo->si_pid
报告为0,因为si_pid
只能通过kill
发出的信号填写。这意味着0传递给getpgid()
,它返回调用进程的PGID
,这与前一行返回的getpgid(pid)
相同。
下面是如果我从另一个进程中使用kill -SIGINT
而不是按^C
来杀死它,会发生什么情况。
$ ./x
before call pgid is 15165 pid=15165
after setpgid call pgid is 15165 pid=15165
after tcsetprgrp call pgid is 15165 pid=15165
in signal handler pid is 15165, getpgid(pid) is 15165
in signal handler siginfo->si_pid is 14858, getpgid(siginfo->si_pid) is 14858
正如您所看到的最后一行报告发送kill
的进程的PID。
在上述两个示例中,当进程启动时,PGID
已经等于PID
。这是为什么?那么,我们从命令行启动了一个命令,因此只有一个进程组,所以PGID
总是会是PID
。
那么如果我们启动一个流程组,那么我们不是第一个流程会发生什么?试试这个:
$ echo | ./x
before call pgid is 15173 pid=15174
after setpgid call pgid is 15174 pid=15174
after tcsetprgrp call pgid is 15174 pid=15174
in signal handler pid is 15174, getpgid(pid) is 15174
in signal handler siginfo->si_pid is 14858, getpgid(siginfo->si_pid) is 14858
注意这一个我曾与kill -SIGINT
杀死,因为^C
去这是(在PGID
变更后)的过程组只echo
。因此,输入的PGID
是15173
(PID为echo
),但被更改为15174
(按照您的要求)。
我认为这一切都按预期工作。
我认为你的问题本质上是在你的信号处理程序中。首先,你似乎在期待si_pid
来填写。其次,你printf
说你要打印pgid
和shell_pgid
(二PGID
S,而实际上要打印的过程中发出的击杀PGID
(或getpgid(0)
如果没有结果这是调用进程的PGID
),则进程的PID - 即两个方向错误和PID
和PGID
同时我也怀疑设立处理程序错误可能会给你一个垃圾第二个参数反正
。是''setpgid()'调用成功吗? – abligh 2014-10-27 17:42:16
@abligh是的它确实 – Mariska 2014-10-27 18:48:59