[请教内核高手]内核在何处处理接收到的信号
C/C++ code
#include <signal.h>
#include <stdio.h>
static void alarm_handler(int signo)
{
printf("3 seconds end.\n");
alarm(3);
}
int main(void)
{
// 该程序仅仅做测试,故无错误检查
struct sigaction act;
act.sa_handler = alarm_handler;
act.sa_flags = 0;
sigempty(&act.sa_mask);
sigaction(SIGALRM, &act, NULL);
alarm(3);
while(1);
return 0;
}
我的主程序在设置了alarm值之后直接进入无系统调用的死循环中,当内核的调度程序检测到该进程alarm<jiffies时,就会向该进程发送 SIGALRM 信号,但不会处理该信号,而且由于是死循环,该进程一直处于 RUNNING 状态(这个我有点不确定),也就没有被唤醒一说。但实际上这个信号却是被处理了,我想问到底在内核哪个部分处理这个信号的?求高手解答。
------解决方案--------------------[User:root Time:10:04:50 Path:/home/liangdong/c]$ make
gcc -g -I./include -c -o src/main.o src/main.c
gcc -o output src/main.o -lpthread -lm -lz
Makefile done.
[User:root Time:10:04:51 Path:/home/liangdong/c]$ ./output
3 seconds end.
3 seconds end.
3 seconds end.
3 seconds end.
3 seconds end.
3 seconds end.
3 seconds end.
3 seconds end.
3 seconds end.
3 seconds end.
^C
我看到的是假象?
------解决方案--------------------信号的处理时机是在从内核态切换到用户态时,会执行do_signal()函数来处理信号
你的while(1)死循环并不代表进程一直运行在用户态,系统时钟中断的会在内核态更新当前进程的使用时间相关的变量,因此while(1)也会在内核态和用户态切换,此时就是信号处理的时机
------解决方案--------------------主要是通过拷贝进程上下文来实现的。
do_signal()调数调用handle_signal(),这些都运行在内核态,而handle_signal()函数会真正地去执行用户态的信号处理函数。这时Linux把保存在内核栈的硬件上下文拷贝到用户态栈(通过setup_frame()),并把进程切换到用户态去执行信号处理函数。当处理程序终止时,sigreturn()再把用户态栈上下文拷贝到内核栈,并恢复用户态栈。
------解决方案--------------------《深入理解linux内核》“信号”章节书中有讲是如何实现的