我认为您可能对进程组 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)
{
}
}
主要的变化是,如果你的处理程序接受三个参数,你需要在not中使用SA_SIGINFO
并指定处理程序。否则,您的处理程序可能会得到无效的第二个和第三个参数。sa_sigaction
sa_handler
接下来,我修复了您的处理程序,使其打印出来si_pid
以及pid
.
我还进行了一些额外的调试。
这就是我直接从 shell 运行时发生的情况:
$ ./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()
which 返回调用进程的 ,这与上一行返回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
.
在上述两个示例中,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
因为 a^C
进入进程组(在PGID
更改之后) only echo
。因此,PGID
on 条目是15173
(的 PID echo
),但被更改为15174
(根据您的要求)。
我认为这一切都按预期工作。
我认为您遇到的问题本质上在于您的信号处理程序。首先,您似乎期望si_pid
被填写。其次,您printf
说您正在打印pgid
and shell_pgid
(两个PGID
s,而实际上您正在打印PGID
发出 kill 的进程的 the (或者如果没有,其结果getpgid(0)
是PGID
调用进程的),然后是进程的 PID - 即错误的方式和 aPID
和 a PGID
。而且我怀疑设置错误的处理程序可能会给你一个垃圾的第二个参数。