在通过sigaction()
使用SA_SIGINFO
标志设置的信号处理程序中,si_pid
结构的siginfo_t
成员(存储发送进程ID)为零时SIGINT
是通过CTRL-C
为了简单起见,请使用以下使用signalfd()
的示例来演示“问题”:
#include <sys/signalfd.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main(void) {
sigset_t mask;
int sfd;
struct signalfd_siginfo fdsi;
ssize_t s;
printf("my process id: %d\n", getpid());
sigemptyset(&mask);
sigaddset(&mask, SIGINT);
/* block signals to avoid default handling */
if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) {
perror("sigprocmask");
return 1;
}
sfd = signalfd(-1, &mask, 0);
if (sfd == -1) {
perror("signalfd");
return 1;
}
printf("waiting for sigint ...\n");
/* raise(SIGINT); */
s = read(sfd, &fdsi, sizeof(struct signalfd_siginfo));
if (s != sizeof(struct signalfd_siginfo)) {
perror("reading from signal fd");
return 1;
}
if (fdsi.ssi_signo != SIGINT) {
fprintf(stderr, "received unexpected signal %d\n", fdsi.ssi_signo);
return 1;
}
printf("received SIGINT from process %d\n", fdsi.ssi_pid);
return 0;
}
如果您运行此程序并从另一个tty触发kill -INT pid
,则该程序的输出为:
my process id: 23540
waiting for sigint ...
received SIGINT from process 23186
现在,如果您在启动程序后按CTRL-C
,则输出为:
my process id: 23551
waiting for sigint ...
^Creceived SIGINT from process 0
如果我在程序中引发SIGINT(通过取消注释代码示例中的行/* raise(SIGINT); */
),则输出为:
my process id: 23577
waiting for sigint ...
received SIGINT from process 23577
现在,如果我为kill
,tkill
和tgkill
启用了linux ftrace系统调用跟踪器,我可以验证信号是否由sys_kill
处理第一个示例和最后一个示例中的sys_tgkill
。
但是,按CTRL-C
时,不会调用这些系统调用。
问题:
按下CTRL-C
时会调用哪个(如果有)系统调用?
谁将指令指针传递给CTRL-C
上的系统调用处理程序?
为什么发件人pid siginfo_t
CTRL-C
上的{0}}(错误或记录的功能)?
答案 0 :(得分:2)
当SIGINT
因CTRL-C
被按下而被SIGINT
发送时,任何进程都不会调用任何系统调用。这就是发送者的PID为零的原因。
信号从内核发送。具体来说,是TTY模块。每个过程(可选地)连接到终端,即“控制终端”。每个终端都有一个定义的密钥序列,它为绑定到终端的所有进程生成CTRL-C
。默认的键序列当然是CTRL-C
。
在这种情况下,您可以将PID 0视为“内核进程”。
参考:
看看你是否可以在stty的输出中发现$ stty -a
speed 38400 baud; rows 24; columns 80; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = M-^?; eol2 = M-^?;
swtch = M-^?; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W;
lnext = ^V; discard = ^O; min = 1; time = 0;
-parenb -parodd -cmspar cs8 hupcl -cstopb cread -clocal -crtscts
-ignbrk brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff
-iuclc ixany imaxbel iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt
echoctl echoke -extproc
:
.tt