我想你可能對過程組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