【问题标题】:Signal control in CC中的信号控制
【发布时间】:2015-10-24 16:26:49
【问题描述】:

是否可以确保 C 中的信号调用顺序?我们看下面的代码:

//main.c
int counter;
pid_t pid;

void alrm_handler(int s)
{
    kill(pid, SIGUSR1);
    alarm(1);
    --counter;
    if (counter == 0)
        kill(pid, SIGTERM);
    printf("%d\n", counter);
    fflush(stdout);
}

int main(int argc, char* argv[])
{
    counter = atoi(argv[1]);
    signal(SIGALRM, alrm_handler);
    alarm(1);

    pid = fork();
    if (!pid)
        execl("child", "child", NULL);

    wait(NULL);

    return 0;
}

//child.c
void usr1_handler(int s)
{
    puts("TEXT");
    fflush(stdout);
}

int main()
{
    signal(SIGUSR1, usr1_handler);

    while(1)
    {
        struct timespec T;
        T.tv_nsec = 100;
        T.tv_sec = 0;
        nanosleep(&T, NULL);
    }

    return 0;
}

即使我发送 SIG_USR1 3 次,我也只能得到 2 次输出。似乎 SIGTERM 具有更高的优先级或其他东西。在这种情况下如何实现 3 个输出?

【问题讨论】:

  • 发布的代码实现了一个嵌套/递归信号处理程序,这是一个禁忌。发布的代码实现了对 I/O 函数 printf() 的调用,这是一个禁忌。第一个发布的代码不正确地处理来自 fork() 的返回值,并且似乎期望对 execl() 的调用永远不会失败。
  • 我不是在问这段代码有什么错误(为了简单起见,我省略了一些东西)。我所要求的只是一种确保 sigterm 不会在 sigusr1 之前到达的方法。我认为这并不总是可能的。 SIGTERM 可能比 SIGUSR1 具有更高的优先级,这就是它们按此顺序到达的原因。
  • 该网站的大多数程序员都是“新人”,不会知道“来自辣椒的错误”。所以我尝试指出实际问题范围之外的编码问题,以便“新”程序员可以学习

标签: c unix concurrency


【解决方案1】:

您的示例程序存在一个会影响输出顺序的问题,即您在信号处理程序中使用了缓冲 I/O。除了不安全之外,这些操作不一定按照您期望的顺序完成。

有关讨论,请参阅

【讨论】:

    【解决方案2】:

    开放组基本规范第 6 期 IEEE Std 1003.1, 2004 版:

    外部多个同时挂起的信号的顺序 SIGRTMIN 到 SIGRTMAX 的范围被传递给或接受 进程未指定。

    您的父进程运行得如此之快,以至于它可能在子进程能够接收它之前发送SIGUSR1SIGTERM,因此子进程有两个待处理信号并且未指定顺序(读取实现定义——任何顺序都是可能)。

    【讨论】:

      猜你喜欢
      • 2023-02-08
      • 2021-05-20
      • 2011-11-07
      • 2019-06-19
      • 2017-04-29
      • 2011-08-31
      • 1970-01-01
      • 1970-01-01
      • 2010-11-28
      相关资源
      最近更新 更多