【发布时间】: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