如果已经设置了警报,则alarm()的返回值是什么

时间:2016-12-26 17:35:35

标签: c unix signals alarm

在APUE书的第10章信号中,有一个示例代码:

#include <signal.h>
#include <unistd.h>

static void sig_alrm(int signo) {
    /* nothing to do, just return to wake up the pause */
}

unsigned int sleep1(unsigned int seconds) {
   if (signal(SIGALRM, sig_alrm) == SIG_ERR)
       return(seconds);

    alarm(seconds);     /* start the timer */
    pause();            /* next caught signal wakes us up */
    return(alarm(0));   /* turn off timer, return unslept time */
}

int main() {
    sleep1(1);
    return 0;
}

简单地实现&#34; imcomplete&#34;睡眠()。

这本书说&#34;这个功能看起来像睡眠功能,但是这个 简单的实现有三个问题。&#34;

  1. 如果来电者已经设置了闹钟,则首次呼叫闹钟会清除该闹钟。我们可以通过查看报警的返回值来纠正这个问题。如果直到某些先前设置的警报的秒数小于参数,那么我们应该等到现有警报到期为止。如果先前设置的警报在我们之后发生,那么在返回之前我们应该将此警报重置为将来指定的时间。

  2. 我们修改了SIGALRM的处理方式。如果我们正在编写一个函数供其他人调用,我们应该在调用函数时保存处理,并在完成后恢复它。我们可以通过保存信号的返回值并在函数返回之前重置处置来纠正这个问题。

  3. 第一次报警和暂停呼叫之间存在竞争条件。在繁忙的系统上,警报可能会关闭,并且在我们调用暂停之前调用信号处理程序。如果发生这种情况,调用者将暂停在暂停调用中(假设未捕获其他信号)。

  4. 我对上述三个陈述有疑问:

    1. 有人可以为statement1提供一些示例代码吗?

    2. 我不知道声明2的内容,有人可以给我强有力的解释吗?

    3. 我不知道为什么声明3会导致竞争状况。

    4. 非常感谢!

2 个答案:

答案 0 :(得分:1)

你的Q1:

int r1 = alarm(20);
printf("r1 = %d\n", r1);
int r2 = alarm(10);
printf("r2 = %d\n", r2);

这通常会打印r1 = 0r2 = 20,因为在第一次通话时没有设置闹钟,而在第二次通话时仍有20秒的时间。此时,还有10秒钟,直到闹钟响起。只安排了一个警报信号。因此,您无法设置10秒,20秒和53秒的警报;你最多可以有其中一个待定。

你的Q2:

  • 如果调用sleep1()的代码已经将信号处理程序设置为处理SIGALRM,那么您就会抛弃该信息。您应该从signal(SIGALRM, sig_alrm)捕获返回值,并在sleep1()完成时恢复该值。 (如果将其设置为SIG_IGN,则不清楚应该怎么做。)

你的Q3:

  • 调度不是确定的。您的流程可以调用alarm(1),然后暂停。在重新安排程序之前,它可能会超过一秒钟,并且会在返回执行pause()之前发现警报已关闭并处理警报。然后,您对pause()的调用将无限期挂起该程序,因为没有警报等待唤醒它。你必须以某种方式发送信号。

答案 1 :(得分:1)

在标题中回答你的问题。

返回值是先前调用alarm()

时剩余的秒数