【问题标题】:Unix and Signal Handlers (C)Unix 和信号处理程序 (C)
【发布时间】:2017-05-06 17:43:57
【问题描述】:

我是一名学生,我正在尝试了解有关 Unix 编程的课程中的信号。

首先,我想测试一个简单的示例:一个进程生成了一个子进程,并且需要确认实际创建。 我分叉,并在孩子内部发送一个 SIGUSR1 给父亲 杀死(getppid(),SIGUSR1); 然后,在父亲内部,我写了一个 pause(); sys 调用来阻塞进程,直到收到信号,然后我写了 (sigaction(SIGUSR1, &sa, NULL) 检查。

问题是,信号被发送,程序停止,没有处理程序执行。

我用它编译

$gcc -Wall -o test test.c

我没有收到任何警告,输出是

$I am the father
$I am the child
$User defined signal 1

我知道我可以通过其他方式(通过 sleep sys 调用等)做到这一点,但我只是想了解为什么这段代码不起作用。

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

void new_child (int sig){
    write(1,"I made a new child\n",50);
}

int main(){
    pid_t child;
    struct sigaction sa;            
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    sa.sa_handler = new_child;
    switch(child = fork()){
        case -1:
            printf("Error.\n");
            exit(EXIT_FAILURE);
        case 0:
            printf("I am the child\n");
            kill(getppid(), SIGUSR1);
            break;
        default:
            printf("I am the father\n");
            pause();
            if (sigaction(SIGUSR1, &sa, NULL) == -1){
                printf("Signal error.\n");
                exit(EXIT_FAILURE);
            }
            printf("I'm done.");
            kill (child, SIGKILL);
            exit(EXIT_SUCCESS);
    }
}

我知道已经有人问过这个问题,但我似乎找不到适合我的解决方案。

【问题讨论】:

  • 您必须更改代码开头的信号,以便在收到 SIGUSR 后立即执行
  • 非常感谢。这确实有效!我发现系统调用 pause() 非常有用,但我的书甚至没有使用示例。
  • write(1,"I made a new child\n",50); 将向文件描述符 1 写入大量垃圾,因为 "I made a new child\n" 的长度远小于 50。这在技术上是未定义的行为,可能会导致您的程序失败。
  • @Anjaneyulu:“你必须改变代码开头的信号……”这个限制有点严格。信号处理程序需要在调用 fork() 之前安装最新。
  • @alk 是信号处理程序而不是信号

标签: c unix concurrency


【解决方案1】:

您必须更改代码开头的信号,以便在收到 SIGUSR 后立即执行 - Anjaneyulu

你必须改变代码开头的信号......”这个限制有点严格。信号处理程序需要在调用fork() 之前安装最新版本。 – alk

【讨论】:

    猜你喜欢
    • 2023-03-17
    • 2019-08-04
    • 2014-08-29
    • 2011-09-25
    • 1970-01-01
    • 2020-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多