C 信号处理程序中的pgid与实际pgid不同
我有一个简单的程序,为STDIN设置主程序的pgid和pgroup。然后,我有一个信号处理程序,它打印当前进程的pgid和发送信号的进程的pgid。这是我的密码C 信号处理程序中的pgid与实际pgid不同,c,signals,process-group,C,Signals,Process Group,我有一个简单的程序,为STDIN设置主程序的pgid和pgroup。然后,我有一个信号处理程序,它打印当前进程的pgid和发送信号的进程的pgid。这是我的密码 pid_t pid; void handler(int signum, siginfo_t* siginfo, void* context){ printf("pgid is %d, shell_pgid is %d \n", getpgid(siginfo->si_pid), pid); } int main()
pid_t pid;
void handler(int signum, siginfo_t* siginfo, void* context){
printf("pgid is %d, shell_pgid is %d \n", getpgid(siginfo->si_pid), pid);
}
int main()
{
struct sigaction sa;
sa.sa_handler = handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sigaction(SIGINT, &sa, NULL);
pid = getpid();
setpgid(pid, pid);
tcsetpgrp(STDIN_FILENO, pid);
while(1){
}
}
但是,当我按下^C时,得到的输出是
^Cpgid is 335, shell_pgid is 3924
难道它们不应该是相同的,因为程序在主程序中运行,信号也从相同的源发送吗 我认为您可能对进程组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)
{
}
}
请注意,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
(echo
的PID),但会更改为15174
(根据您的请求)
我想一切都按预期进行了
我认为你的问题本质上在于你的信号处理器。首先,您似乎希望填写
si_pid
。其次,您的printf
表示您正在打印pgid
和shell\u pgid
(两个pgid
s,而实际上您正在打印发出kill的进程的pgid
(如果没有),则打印getpgid(0)
的结果,这是调用进程的pgid
),然后进程的PID-即错误的循环方式和aPID
和aPGID
。而且我怀疑设置错误的处理程序可能会给您提供第二个参数。是setpgid()
call successing?@abligh我运行了你的程序并在main中终止,但我的输出是221:src frabi$。/getpgid在调用前pgid是4758,在setpgid调用后pgid是4758,在tcsetprgrp调用后pgid是4758,在信号处理程序siginfo->si_pid是335,getpgid是4758(siginfo->si_pid)是335对,所以你直接从shell启动,所以在你开始之前,你的PGID
和你的PID
已经相等了。看起来当你杀死它时,你得到了一个si_PID
集。这可能取决于你的^C
处理是如何完成的。我是通过ssh
登录的。不管怎样,我猜是335是你的壳的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