【问题标题】:Alarm system call on Ubuntu 12.4Ubuntu 12.4 上的报警系统调用
【发布时间】:2013-04-01 02:01:52
【问题描述】:

我个人讨厌这类问题,但我被困住了。我有一个程序要在 Ubuntu 12.4 上运行(内核: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 系统上从来没有收到警报,或者可以做些什么来弄清楚发生了什么?

【问题讨论】:

  • “当我在另一个系统上运行相同的代码时”,已经编译了吗?还是再次从源代码编译?
  • 在其他系统上从源代码编译
  • 你能发布每个内核版本的编译器版本吗?
  • @JorgeIsraelPeña,是的,我添加了它们。还刚刚测试了将二进制文件从 ubuntu 复制到其他 linux 系统并且 SIGALRM 正在通过那里。
  • 哦,好吧,那么从问题系统中获取已编译的二进制文件在其他系统上是否有效?我不热衷于哭泣“系统(内核,编译器等)错误”,但我无法解释其他任何事情。也许其他人有另一个想法。你编译的很简单?没有像_BSD_SOURCE 这样可能使用feature test macros 的复杂makefile?

标签: c ubuntu signals virtualbox


【解决方案1】:

您不能安全地调用 printf() 或信号处理程序中的大量其他 i/o 函数。它有时有效,但不可靠。它不是异步信号安全的。查看其他列表:http://man7.org/linux/man-pages/man7/signal.7.html

然而,它有时会“意外”起作用,使人们认为它通常是可以接受的。

尝试在信号处理程序内部增加一个变量,然后在信号处理程序外部检查它的值是否发生变化。

【讨论】:

  • 感谢您的评论。我清空了所有内容的 bell 功能,但该过程仍然无法通过 pause 功能。
  • 除此之外,我看不出你在做什么有什么问题,而且,虽然我确定你不想听到这个,但它在这里工作得很好,但我' m 没有运行 Ubuntu。您是否有机会在另一个系统(不是 Ubuntu,其他 Linux 发行版)上编译它并将其复制过来看看会发生什么?可能是工具链/库问题。
  • :) 谢谢,刚刚尝试将编译后的版本从第二台机器拉到 Ubuntu 机器上,同样的行为正在发生。
【解决方案2】:

我认为问题在于信号永远不会被触发的可能性。毕竟,strace 显示 rt_sigaction 返回 0 表示设置信号处置成功。我认为SIGALRM 信号根本不会被发送。

编辑:似乎是这样。我希望@Gonzalo 不介意我引用 VirtualBox ticket he posted 标题为“SIGALRM 永不触发”。你说你在虚拟盒子上测试。它似乎确实反映了这种行为。

【讨论】:

  • 感谢代码,这是个好主意。切换它没有帮助,进程仍然永远无法通过暂停功能。
  • 我同意这个分析,
  • @Nate 是的,责怪内核是很少见的(因为我们排除了编译器)。起初我怀疑它可能是内核,但后来我又不知道你在 VirtualBox 环境中运行哈哈。希望您的问题现在得到解决。
猜你喜欢
  • 2014-01-12
  • 2013-12-20
  • 2015-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多