我必须编写一个 C 程序来检查 init 如何响应不同的终止信号,但是我不确定如何记录它 - 例如,信号编号 14 会使 ubuntu 崩溃,然后某个更高的信号会将其关闭。有没有办法正确地记录它,以便我知道系统如何响应每个信号?这是我使用的 C 代码,任何反馈也将不胜感激:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int sigs[64] = { 0 };
for(int i = 0; i < 64; i++) sigs[i] = i+1;
char sigs_char[64][2];
for(int i = 0; i < 64; i++) sprintf(sigs_char[i], "%d", sigs[i]);
char one[2] = " 1";
char commands[64][128];
for(int i = 0; i < 64; i++){
strcpy(commands[i], "sudo kill -s ");
strncat(commands[i], sigs_char[i], 2);
strcat(commands[i], one);
}
for(int i = 0; i < 64; i++){
printf("Sending signal number %d\n", i);
system(commands[i]);
}
return 0;
}
答案1
恐怕没有通用的方法来“记录”init
的反应。首先,事实是kill
不会向 发送任何未处理的信号init
(init
来自man 2 kill
):
NOTES
The only signals that can be sent to process ID 1, the init process,
are those for which init has explicitly installed signal handlers.
This is done to assure the system is not brought down accidentally.
因此,对于许多信号来说,根本不会有反应。现在剩下的信号是是处理。使用这个Unix和Linux问题,我们可以确定那些1:
$ HANDLED_SIGS=$(awk '/SigCgt/{print "0x"$2}' /proc/1/status)
$ for i in {0..31}; do (( (1 << i) & $HANDLED_SIGS )) && echo $((++i)) $(/bin/kill --list=$i); done | column
1 HUP 6 ABRT 11 SEGV 15 TERM 30 PWR
2 INT 10 USR1 14 ALRM 17 CHLD 32
这些:
SIGABRT
并SIGSEGV
导致核心转储和内核崩溃。这里没有检测到任何东西。SIGTERM
导致它重新加载,日志消息如下/var/log/syslog
:Nov 14 00:25:13 vm kernel: [32383.384907] init: upstart-udev-bridge main process (395) terminated with status 1 Nov 14 00:25:13 vm kernel: [32383.384916] init: upstart-udev-bridge main process ended, respawning Nov 14 00:25:13 vm kernel: [32383.384990] init: upstart-socket-bridge main process (649) terminated with status 1 Nov 14 00:25:13 vm kernel: [32383.384995] init: upstart-socket-bridge main process ended, respawning Nov 14 00:25:13 vm kernel: [32383.385059] init: upstart-file-bridge main process (953) terminated with status 1 Nov 14 00:25:13 vm kernel: [32383.385074] init: upstart-file-bridge main process ended, respawning
SIGINT
导致它开始重新启动,并SIGPWR
开始关机。两者看起来都像正常的(例如,就像你做了一样reboot
)。- 其余均未造成任何明显影响。(不过,考虑到
init
的职责,我们可以猜出什么SIGCHLD
造成了影响。)
所有这些都是为了 Upstart。谁知道 SysV 或 systemd 会如何反应?
所以,总而言之,你在这里使用经验方法不会有太大的运气。使用来源,卢克。
1init
这段复杂的代码是为了获取愿意捕获的信号:
HANDLED_SIGS=$(awk '/SigCgt/{print "0x"$2}' /proc/1/status)
for i in {0..31}
do
(( (1 << i) & $HANDLED_SIGS )) && echo $((++i)) $(/bin/kill --list=$i);
done | column
HANDLED_SIGS=$(awk '/SigCgt/{print "0x"$2}' /proc/1/status)
:/proc/$PID/status
包含有关该过程的大量信息,包括处理的信号集。该集合由 给出SigCgt
,即以十六进制数给出的位掩码。我们使用awk
提取该数字并添加0x
为前缀。(( (1 << i) & $HANDLED_SIGS ))
:检查信号号是否(i+1)
被屏蔽。由于我们关心的是第i
位,因此我们使用 2 (i-1)(即1 << i
)。对于(( ))
,非零值表示成功。