【问题标题】:sleep2 works not properly in apue?sleep2 在 apue 中不能正常工作?
【发布时间】:2014-02-13 18:38:45
【问题描述】:

sleep2的apue中代码如下:

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

static jmp_buf env_alrm;

static void sig_alrm(int signo)
{
    longjmp(env_alrm, 1);
}

unsigned int sleep2(unsigned int nsecs)
{
    if(signal(SIGALRM, sig_alrm) == SIG_ERR)
    {
        return (nsecs);
    }

    if(setjmp(env_alrm) == 0)
    {
        alarm(nsecs);
        pause();
    }

    return (alarm(0));
}

int main(void)
{
    while(1)
    {
        sleep2(1);
        printf("test\n");
    }
    return 0;
}

代码的输出只是一个字符串“test”然后挂掉

据我了解,sleep2 函数的工作原理如下:

  1. jmp_buf env_alrm 设置为 0
  2. 程序第一次调用sleep2时,会调用alarm(nsecs)
  3. 在 nsecs 时,sig_alrm 将被调用,longjpm 将 env_alrm 结构设置为 1
  4. 然后它跳转到if(setjmp(env_alrm) == 0),虽然它不是真的,所以它运行语句return alarm(0)

在第二次调用 sleep2 时,struct jmp_buf env_alrm 的值为 1,因此不会调用 alrm(nsecs),在我看来,这就是导致功能无法正常工作的原因,所以我将代码更改为如下:

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

static jmp_buf env_alrm;

static void sig_alrm(int signo)
{
    longjmp(env_alrm, 1);
}

unsigned int sleep2(unsigned int nsecs)
{
    if(signal(SIGALRM, sig_alrm) == SIG_ERR)
    {
        return (nsecs);
    }

    alarm(nsecs);
    if(setjmp(env_alrm) == 0)
    {
        pause();
    }

    return (alarm(0));
}

int main(void)
{
    while(1)
    {
        sleep2(1);
        printf("test\n");
    }
    return 0;
}

但是,第二个程序产生与第一个程序相同的输出,所以我的问题是:

是什么让这两个程序只打印一个“测试”然后挂起?

【问题讨论】:

    标签: c linux signals


    【解决方案1】:

    您的代码与书上的代码执行相同的操作。每当信号处理程序 longjmp() 到 sleep2() 时,alarm() 就永远不会(并且永远不会)再次执行。对于您的问题,我建议您继续阅读本书,直到有关 sig_setjmp() 函数的部分。 由于我不了解您的系统,我认为挂断很可能是由于 longjmp() 没有恢复信号掩码。这意味着您第一次进入信号处理程序时,系统会自动屏蔽此信号以避免重入。并且当处理程序返回此屏蔽信号(在您的情况下为 SIGALRM)时,将被取消屏蔽(恢复)。 POSIX 没有定义 longjmp() 是否应该恢复这个信号。所以你可能在处理程序中屏蔽了 SIGALRM 并且没有取消屏蔽它。因此程序卡在第二个循环上。 要验证这一点,您可以在 sig_alrm() 处理程序中使用 pr_mask() 函数。这是作者编写的打印当前进程掩码的函数。让我知道结果。

    【讨论】:

      猜你喜欢
      • 2013-06-29
      • 2021-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多