我试着测试信号处理程序中到底发生了什么。
int num = 0;
void handler(int signum, siginfo_t *sip, void *ptr)
{
sleep(1);
num ++;
write(1, "processs!n", 10);
}
int main(void)
{
int pid = getpid();
struct sigaction act1;
printf("%dn", pid);
//act1.sa_flags = SA_NODEFER;
act1.sa_sigaction = &handler;
sigaction(SIGUSR1, &act1, NULL);
sigaction(SIGUSR2, &act1, NULL);
while (1)
{
sleep(1);
printf("%dn", num);
};
}
在另一个进程中,我发送了两个信号,结果是这样的:杀(pid, SIGUSR1);杀(pid, SIGUSR1);据我所知,信号处理程序阻塞了调用自己的信号.....阻塞信号在处理程序结束后被处理。我希望处理程序将被调用两次,全局变量num将为2;
但是它只被调用了一次并且num是1
然后我试着发送两个不同的信号,像这样:杀(pid, SIGUSR1);杀(pid, SIGUSR2);
据我所知,SIGUSR2将在处理程序仍处于睡眠状态时被处理,并且第一个处理程序将在这里退出,并且num ++将无法工作。它将在稍后调用的处理程序中只处理一次。
但是在这个试验中调用了两次处理程序并且num为2 ....
我对信号处理程序的想法是否有任何误解?我很困惑。
这是你的误解:
和第一个处理程序将在这里退出,num ++将无法工作。
当一个信号处理程序中断另一个信号处理程序时,一旦中断的信号处理程序结束,被中断的信号处理程序就从它离开的地方恢复。它不仅仅是提前结束。
顺便说一下,你的代码有很多问题:- 因为你不使用
SA_SIGINFO
,你的handler
应该只接受一个参数,应该在sa_handler
而不是sa_sigaction
。 - 你没有初始化
struct sigaction
的大多数字段,所以当你调用sigaction
时,可能会发生非常奇怪的事情。 - 你真的被限制在你被允许从信号处理程序内部做什么;特别是,不允许访问
int
类型的全局变量。修改num
为volatile sig_atomic_t
- 你基本上不应该在循环之外使用
write
,因为部分写基本上是允许在任何时候发生的。
至于为什么发送SIGUSR1
两次并不总是运行处理程序两次,那是因为非实时信号被允许合并,所以如果你的第二个kill
发生在第一个信号处理程序开始运行之前,那么第二个有效地不会做任何事情。