我个人讨厌这些问题,但我被困住了。我有一个程序,我正在尝试运行 Ubuntu 12.4 (kernal:Linux 3.2.0-39-generic-pae#62-Ubuntu SMP i686 i686 i386 GNU / Linux;编译器:gcc(Ubuntu / Linaro 4.6.3-1ubuntu5)4.6.3):
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
/*
* sleep1.c
* purpose show how sleep works
* usage sleep1
* info sets handler, sets alarm, pauses, then returns
*/
int main()
{
void onbell(int);
printf("about to sleep for 4 seconds\n");
signal(SIGALRM, onbell); /* catch it */
alarm(4); /* set clock */
pause(); /* do nothing */
printf("Morning so soon?\n"); /* back to work */
return 0;
}
void
onbell(int s)
{
printf("Alarm received from kernel\n");
}
问题是, SIGALRM 永远不会出现。如果我在其上运行 strace ,最后三行是:
rt_sigaction(SIGALRM, {0x80484c1, [ALRM], SA_RESTART}, {SIG_DFL, [], 0}, 8) = 0
alarm(4) = 0
pause(
暂停永不返回。当我在使用 Kernal报告自己的系统上运行相同的代码时:Linux 2.6.24-32-generic i686 GNU / Linux;编译器:gcc(GCC)4.2.4(Ubuntu 4.2.4-1ubuntu4)运行strace的相同代码显示:
rt_sigaction(SIGALRM, {0x8048470, [ALRM], SA_RESTART}, {SIG_DFL}, 8) = 0
alarm(4) = 0
pause() = ? ERESTARTNOHAND (To be restarted)
--- SIGALRM (Alarm clock) @ 0 (0) ---
write(1, "Alarm received from kernel\n", 27Alarm received from kernel
) = 27
知道为什么警报永远不会在 Ubuntu 12.4 系统中被选中,或者可以做些什么来弄清楚发生了什么?
答案 0 :(得分:1)
您无法安全地从信号处理程序中调用printf()或其他相当多的I / O函数。它有时可行,但不可靠。这不是异步信号安全的。有关其他人的列表,请参阅此页:http://man7.org/linux/man-pages/man7/signal.7.html
然而,它有时会“意外地”工作,让人们认为它通常是可以接受的。尝试在信号处理程序中增加一个变量,然后检查它在信号处理程序之外的值是否有变化。
答案 1 :(得分:0)
我认为问题在于信号永远不会被触发的可能性。毕竟,strace显示rt_sigaction
返回0表示设置信号处置成功。我认为永远不会发送SIGALRM
信号。
编辑:看来情况确实如此。我希望@Gonzalo不介意我引用标题为“SIGALRM永远不会触发”的VirtualBox ticket he posted。你说你在虚拟盒子上测试。它似乎反映了这种行为。