管道()和叉子()
Pipe() and fork()
我的程序的目标是创建两个管道和两个相互通信的进程,以读取和写入管道。
- 进程 p1 从管道 c1 读取并写入管道 c2
- 进程 p2 从管道 c2 读取并写入管道 c1
直到从管道读取的数字小于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);
}
你的程序有点奇怪。主要问题似乎是第二个 fork 在主程序和第一个子程序中执行。实际上你是运行四个进程:main,main的两个儿子和第一个儿子的儿子。这可能不是您想要的。您可能希望将第一个 switch
紧跟在第一个 fork
之后,并仅在主程序中执行第二个 fork
。
当然,您不会检查 read
和 write
的结果值以发现意外情况。
问题是 p2 分叉了 2 次。一次在父进程,第二次在p1进程。
而不是:
p1 = fork();
p2 = fork();
你需要这样写:
p1 = fork();
if (p1 > 0) {
p2 = fork();
}
您的代码没有对 read
和 write
的调用进行正确的错误检查,这意味着如果从管道读取时出现问题,子进程将进入永无止境的循环因为 c
的值永远不会达到终止值。
由于您的子进程在完成后关闭管道,因此您很有可能进入竞争状态,其中一个进程在另一个进程读取 c
的最新值之前关闭管道.您调用 fork
的位置使情况更加复杂,因为目前您最终得到 3 个子进程,而不是 2 个。
您应该在 switch
之后将第二次调用移至 fork
因为您知道此时您只能在父进程中并将管道的关闭移动到父进程.
我的程序的目标是创建两个管道和两个相互通信的进程,以读取和写入管道。
- 进程 p1 从管道 c1 读取并写入管道 c2
- 进程 p2 从管道 c2 读取并写入管道 c1
直到从管道读取的数字小于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);
}
你的程序有点奇怪。主要问题似乎是第二个 fork 在主程序和第一个子程序中执行。实际上你是运行四个进程:main,main的两个儿子和第一个儿子的儿子。这可能不是您想要的。您可能希望将第一个 switch
紧跟在第一个 fork
之后,并仅在主程序中执行第二个 fork
。
当然,您不会检查 read
和 write
的结果值以发现意外情况。
问题是 p2 分叉了 2 次。一次在父进程,第二次在p1进程。
而不是:
p1 = fork();
p2 = fork();
你需要这样写:
p1 = fork();
if (p1 > 0) {
p2 = fork();
}
您的代码没有对 read
和 write
的调用进行正确的错误检查,这意味着如果从管道读取时出现问题,子进程将进入永无止境的循环因为 c
的值永远不会达到终止值。
由于您的子进程在完成后关闭管道,因此您很有可能进入竞争状态,其中一个进程在另一个进程读取 c
的最新值之前关闭管道.您调用 fork
的位置使情况更加复杂,因为目前您最终得到 3 个子进程,而不是 2 个。
您应该在 switch
之后将第二次调用移至 fork
因为您知道此时您只能在父进程中并将管道的关闭移动到父进程.