简体   繁体   English

Pipe()和fork()

[英]Pipe() and fork()

The goal of my program is to create two pipes and two processes that communicate each other reading and writing to the pipes. 我的程序的目标是创建两个管道和两个进程,以相互交流对管道的读写。

  1. process p1 reads from pipe c1 and writes to the pipe c2 进程p1从管道c1读取并写入管道c2
  2. process p2 reads from pipe c2 and writes to the pipe c1 进程p2从管道c2读取并写入管道c1

Until the read number from the pipe is less than BIG_INT_STOP the two processes continue to increment the number in the pipes. 直到从管道读取的数目小于BIG_INT_STOP,两个过程才继续增加管道中的数目。 As soon as this condition is true, first process that reads it, close the pipes, exit and prints the number. 此条件成立后,首先进行读取,关闭管道,退出并打印数字。 The problem is: when the process p2 ends before p1 it works and when the process p1 ends before p2 it goes in loop. 问题是:当进程p2在p1之前结束时,它起作用;而当进程p1在p2之前结束时,它进入循环。 Can you explain me why? 你能解释一下为什么吗?

#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);
}

Your program is a bit strange. 您的程序有点奇怪。 The main problem seems to be that the second fork is executed in both main program and in the first child. 主要问题似乎是第二个fork在主程序和第一个孩子中都被执行。 In fact you are running four processes: main, two sons of main and the son of the first son. 实际上,您正在运行四个过程:main,main的两个儿子和长子的儿子。 This is probably not what you want. 这可能不是您想要的。 You probably wanted to put the first switch immediately after the first fork and to execute the second fork only in the main program. 您可能想将第一个switch放在第一个fork之后,而仅在主程序中执行第二个fork

And, of course, you are not checking result values of read and write for unexpected situations. 而且,当然,你是不是检查的结果值readwrite的意外情况。

Problem is p2 is forked 2 times. 问题是p2分叉了2次。 Once in parent process, and second time in p1 process. 在父进程中一次,在p1进程中第二次。

Instead of: 代替:

  p1 = fork();
  p2 = fork();

You need to write like this: 您需要这样写:

p1 = fork();
if (p1 > 0) {
        p2 = fork();
}

Your code doesn't do proper error checking on the calls to read and write which means that if there is a problem reading from the pipes, the child will enter a never ending loop as the value of c will never reach the termination value. 您的代码不进行正确的错误校验,来电来readwrite ,这意味着,如果有从管道读出了问题,孩子会进入永无止境的循环为一体的价值c不会到达终止值。

Since your child processes close the pipes when they're done, you have a very high chance of entering a race condition where one process closes the pipes before the other has read in the latest value of c . 由于子进程完成后会关闭管道,因此您极有可能进入竞争状态,其中一个进程先关闭管道,然后另一个进程读取最新的c值。 This is compounded by the placement of your calls to fork as currently you end up with 3 child processes not 2. 由于您对fork的调用的位置更加复杂,因为当前您最终拥有3个子进程而不是2个子进程。

You should move the second call to fork after the switch as you know that at that point you can only be in the parent process and also move the closing of the pipes to the parent. 您应该将第二个调用移至switch之后的fork ,因为您知道那时您只能在父进程中,而且还将管道的关闭位置移到父进程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM