我的程序的目标是创建两个管道和两个进程,彼此通信读取和写入管道。
直到管道中的读数小于BIG_INT_STOP,两个进程继续增加管道中的数字。一旦这个条件成立,第一个进程读取它,关闭管道,退出并打印数字。 问题是:当进程p2在p1之前结束时它起作用,当进程p1在p2之前结束时它进入循环。 你能解释一下为什么吗?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/sysinfo.h>
#include <sys/wait.h>
#include <errno.h>
#include <time.h>
#include <string.h>
#define BIG_INT_STOP 40
#define TEST_ERROR if (errno) {fprintf(stderr, \
"%s:%d: PID=%5d: Error %d (%s)\n", \
__FILE__, \
__LINE__, \
getpid(), \
errno, \
strerror(errno));}
int main(){
int c1[2], c2[2], p1, p2, z;
long a = 0, c;
pipe(c1);
pipe(c2);
write(c1[1], &a, sizeof(a));
write(c2[1], &a, sizeof(a));
p1 = fork();
p2 = fork();
switch(p1){
case -1:
TEST_ERROR;
exit(EXIT_FAILURE);
case 0:
read(c1[0], &c, sizeof(c));
while(c != BIG_INT_STOP){
++c;
write(c2[1], &c, sizeof(c));
read(c1[0], &c, sizeof(c));
}
close(c1[0]);
close(c1[1]);
close(c2[0]);
close(c2[1]);
printf("p1: %ld\n", c);
exit(0);
}
switch(p2){
case -1:
TEST_ERROR;
exit(EXIT_FAILURE);
case 0:
read(c2[0], &c, sizeof(c));
while(c != BIG_INT_STOP){
++c;
write(c1[1], &c, sizeof(c));
read(c2[0], &c, sizeof(c));
}
close(c1[0]);
close(c1[1]);
close(c2[0]);
close(c2[1]);
printf("p2: %ld\n", c);
exit(0);
}
while(wait(&z) != -1);
}
答案 0 :(得分:3)
你的程序有点奇怪。主要问题似乎是第二个fork在主程序和第一个子程序中执行。事实上,你正在运行四个过程:主要的,两个主要的儿子和第一个儿子的儿子。这可能不是你想要的。您可能希望在第一个switch
之后立即放置第一个fork
,并仅在主程序中执行第二个fork
。
当然,对于意外情况,您不会检查read
和write
的结果值。
答案 1 :(得分:1)
问题是p2分叉了2次。一旦进入父进程,第二次进入p1进程。
而不是:
p1 = fork();
p2 = fork();
你需要这样写:
p1 = fork();
if (p1 > 0) {
p2 = fork();
}
答案 2 :(得分:0)
您的代码没有对read
和write
的调用进行正确的错误检查,这意味着如果从管道读取有问题,孩子将进入一个永无止境的循环因为c
的值永远不会达到终止值。
由于您的孩子在他们完成后处理关闭管道,您很有可能进入竞争条件,其中一个进程在另一个进程读取最新值c
之前关闭管道。将您的来电置于fork
会更加复杂,因为目前最终会有3个子流程而不是2个。
您应该在fork
之后将第二次调用移至switch
,因为您知道此时您只能在父进程中,并且还会将管道的关闭移动到父级。 / p>