信号处理程序读取不正确的值
signal handler reading incorrect value
收到 SIGUSR1 信号后,我想显示 child 从管道读取的值。
有个小问题。尽管 parent 进程将 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]);
}
}
`
感谢您的回复。
您似乎假设信号将始终在 read()
完成后处理,但事实并非如此。信号本质上是 异步的 并且可以随时到达(甚至是 read()
的中途!)。基本上,您是在所谓的 竞争条件 上构建程序,您应该真正避免这种情况。
虽然这里肯定存在竞争条件,但这并不是造成麻烦的原因。问题是当 child 进程中的 read() 调用被阻塞时,您的信号被触发。您可以在 parent 过程中添加足够长的暂停,让 child 的 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);
}
当然,关于竞争条件的评论以及您应该避免它们的事实仍然是正确的。此代码不是 "production quality",如果您系统上的负载太重以至于 1 秒不足以安排 child 进程并完成 read() 调用,它将失败。
收到 SIGUSR1 信号后,我想显示 child 从管道读取的值。
有个小问题。尽管 parent 进程将 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]);
}
}
`
感谢您的回复。
您似乎假设信号将始终在 read()
完成后处理,但事实并非如此。信号本质上是 异步的 并且可以随时到达(甚至是 read()
的中途!)。基本上,您是在所谓的 竞争条件 上构建程序,您应该真正避免这种情况。
虽然这里肯定存在竞争条件,但这并不是造成麻烦的原因。问题是当 child 进程中的 read() 调用被阻塞时,您的信号被触发。您可以在 parent 过程中添加足够长的暂停,让 child 的 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);
}
当然,关于竞争条件的评论以及您应该避免它们的事实仍然是正确的。此代码不是 "production quality",如果您系统上的负载太重以至于 1 秒不足以安排 child 进程并完成 read() 调用,它将失败。