在 Linux 中,假设我为用户定义的信号编号(比如信号 10)安装了一个信号处理程序。像:信号(有趣,10);//fun() 作为用户定义信号 10 的信号处理程序
我想问问这背后的背景是什么。我知道每个进程都有一个内部信号处理程序表。但我找不到有关该表的更多信息。
所以,我的问题是一个过程。这些关于信号的信息及其相应的信号处理程序的地址存储在哪里?我如何通过 gdb 查看/检查这些信息?
在 Linux 中,假设我为用户定义的信号编号(比如信号 10)安装了一个信号处理程序。像:信号(有趣,10);//fun() 作为用户定义信号 10 的信号处理程序
我想问问这背后的背景是什么。我知道每个进程都有一个内部信号处理程序表。但我找不到有关该表的更多信息。
所以,我的问题是一个过程。这些关于信号的信息及其相应的信号处理程序的地址存储在哪里?我如何通过 gdb 查看/检查这些信息?
在 Linux 中,信号处理程序按任务存储在struct sighand_struct类型的对象中
struct sighand_struct {
atomic_t count;
struct k_sigaction action[_NSIG];
spinlock_t siglock;
};
该对象通过sighand字段从struct task_struct引用。而不是 gdb (这是一个用户空间的工具),使用crash。
从 task_struct 读取:
crash> p/x *((struct task_struct*)0xdfcb04c0).sighand
$9 = {
count = {
counter = 0x4
},
action = {{
sa = {
sa_handler = 0x0,
sa_flags = 0x0,
sa_restorer = 0x0,
sa_mask = {
sig = {0x0, 0x0}
}
}
}, {
sa = {
sa_handler = 0x0,
sa_flags = 0x0,
sa_restorer = 0x0,
sa_mask = {
sig = {0x0, 0x0}
}
}
}, {
sa = {
sa_handler = 0x0,
sa_flags = 0x0,
sa_restorer = 0x0,
sa_mask = {
sig = {0x0, 0x0}
}
}
}, {
sa = {
sa_handler = 0x4006ac0d,
sa_flags = 0x10000004,
sa_restorer = 0x0,
sa_mask = {
sig = {0x0, 0x0}
}
}
...
因此,我们看到对于信号 4(SIGILL,id 为 0 的信号不存在),用户进程安装了地址为 0x4006ac0d的函数。我们可以通过简单的命令来确认这一点:
crash> sig 0xdfcb04c0
PID: 19658 TASK: dfcb04c0 CPU: 0 COMMAND: "FinalizerWatchd"
SIGNAL_STRUCT: e49f33c0 NR_THREADS: 4
SIG SIGACTION HANDLER MASK FLAGS
[1] e49e8004 SIG_DFL 0000000000000000 0
[2] e49e8018 SIG_DFL 0000000000000000 0
[3] e49e802c SIG_DFL 0000000000000000 0
[4] e49e8040 4006ac0d 0000000000000000 10000004 (SA_SIGINFO|SA_RESTART)
[5] e49e8054 SIG_DFL 0000000000000000 0
[6] e49e8068 4006ac0d 0000000000000000 10000004 (SA_SIGINFO|SA_RESTART)
[7] e49e807c 4006ac0d 0000000000000000 10000004 (SA_SIGINFO|SA_RESTART)
[8] e49e8090 4006ac0d 0000000000000000 10000004 (SA_SIGINFO|SA_RESTART)