收到SIGUSR1信号后,我想显示孩子从管道中读取的值。
有一点问题。尽管getppid()被父进程写入管道,但它总是显示0。有解决方案吗 `
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
char bufP[10], bufC[10];
int gpid;
void handler(int signum){
signal(SIGUSR1, handler);
if (signum == SIGUSR1){
printf("SIGUSR1 received\n");
gpid = atoi(bufC);
printf("Grandparent: %d\n", gpid);
exit(0);
}
}
int main(void){
int pid, fd[2];
pipe(fd);
pid = fork();
signal(SIGUSR1, handler);
if (pid == 0){
//child
close(fd[1]);
read(fd[0], bufC, sizeof(bufC));
close(fd[0]);
}else{
//parent
close(fd[0]);
sprintf(bufP, "%d", getppid());
write(fd[1], bufP, sizeof(bufP));
kill(pid, SIGUSR1);
close(fd[1]);
}
}
`
感谢您的回复。
答案 0 :(得分:1)
您好像假设在<{em> read()
完成后将始终处理信号,但实际情况并非如此。信号本质上是异步,可以随时到达(甚至是read()
的中途!)。基本上你是在一个所谓的竞争条件上构建你的程序,你真的应该避免。
答案 1 :(得分:0)
虽然这里确实存在竞争条件,但并不是造成麻烦的原因。问题是在子进程中的read()调用被阻止时会触发您的信号。您可以在父进程中添加足够长的暂停以让子进程read()完成:
if (pid == 0){
//child
close(fd[1]);
read(fd[0], bufC, sizeof(bufC));
close(fd[0]);
sleep(10); // wait for the signal to arrive
}else{
//parent
close(fd[0]);
sprintf(bufP, "%d", getppid());
write(fd[1], bufP, sizeof(bufP));
close(fd[1]); // close right away to be sure the buffers are flushed
sleep(1); // make sure the child has finished reading the buffer
kill(pid, SIGUSR1);
}
当然,关于种族状况的评论以及你应该避免它们的事实仍然是正确的。此代码不是“生产质量”,如果系统负载过重,1秒不足以安排子进程并完成read()调用,则代码将失败。