c - C pipe fork fd 题 - 简单的 xv6 乒乓球题
问题描述
C新手在这里。我正在尝试在 xv6 中编写一个使用管道、叉子和文件描述符的简单程序。
int
main(int argc, char *argv[])
{
int p[2]; // file descriptors for pipe
char recv_buf[5];
pipe(p);
if (fork() == 0) { // child
read(p[0], recv_buf, 5);
printf("%d: received %s\n", getpid(), recv_buf);
close(p[0]);
write(p[1], "pong", 5);
close(p[1]);
} else { // parent
write(p[1], "ping", 5);
close(p[1]);
read(p[0], recv_buf, 5);
printf("%d: received %s\n", getpid(), recv_buf);
close(p[0]);
}
exit(0);
}
我以为程序会成功打印
$ ./pingpong
$ "3: received ping"
$ "4: received pong"
到终端输出。
相反,输出结果为:
$ ./pingpong
$ "3: received ping"
谁能解释这里发生了什么?我认为每个进程都有自己的文件描述符副本,并且读/写会挂起父进程,直到管道的另一端有输出。那么为什么子进程没有收到“pong”调用呢?
请注意,如果我在父级中添加 wait(0) ,问题就会消失。
int
main(int argc, char *argv[])
{
int p[2]; // file descriptors for pipe
char recv_buf[5];
pipe(p);
if (fork() == 0) { // child
read(p[0], recv_buf, 5);
printf("%d: received %s\n", getpid(), recv_buf);
close(p[0]);
write(p[1], "pong", 5);
close(p[1]);
} else { // parent
write(p[1], "ping", 5);
wait(0); // this fixes the problem. but why?
close(p[1]);
read(p[0], recv_buf, 5);
printf("%d: received %s\n", getpid(), recv_buf);
close(p[0]);
}
exit(0);
}
$ ./pingpong
$ "3: received ping"
$ "4: received pong"
谁能解释为什么 wait(0) 导致程序成功?
解决方案
实际上,我在键入此内容后不久就找到了答案。
第一个程序的程序是在父块内我正在写入输出文件描述符,然后立即从输入文件描述符读取,这意味着父进程不会挂起。
结果是父进程在子进程能够进行任何读/写之前退出。
if (fork() == 0) { // child process never reached
read(p[0], recv_buf, 5);
printf("%d: received %s\n", getpid(), recv_buf);
close(p[0]);
write(p[1], "pong", 5);
close(p[1]);
} else { // parent
write(p[1], "ping", 5); // write to output fd
close(p[1]); // close output fd
read(p[0], recv_buf, 5); // read "ping" from input fd
printf("%d: received %s\n", getpid(), recv_buf); // print "ping"
close(p[0]); // close input fd
}
exit(0); // parent process exists immediately
wait(0) 通过允许子进程在父进程到达读取块之前读取/写入来解决此问题
推荐阅读
- python - 情节:在悬停标签中显示值,而不是在堆积面积图中显示百分比`groupnorm ='percent'`
- php - 如何在 cURL 中使用 shadowsocks 代理?
- javascript - 收到此错误类型错误:无法读取未定义的属性“SearchUserIp”
- python - Tkinter - 无法从另一种方法设置的全局变量中获取值
- ios - 有多个项目的粘贴板
- database - 如何计算配置单元中一条记录的大小?
- python - 使用 Python3 和 imageio 错误地保存 .tif 图像
- python - 如何键入提示在 Python 中返回其参数的可变参数函数
- php - 如何将变量注入另一个值变量
- haskell - 如何添加城市以测试具有数据类型的数据