在c中使用多个管道

时间:2019-05-04 16:19:51

标签: c operating-system

我不会编写使用2个管道在父子进程之间传递值的程序。代码:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/stat.h>
#include <fcntl.h>

int mkfifo(const char *path, mode_t mode);

int main(int argc, char **argv)
{
  int fd,df,val;
  char * myfifo = "/tmp/myfifo";
  mkfifo(myfifo, 0666);

  char * myfifo2 = "/tmp/myfifo2";
  mkfifo(myfifo2, 0666);

  pid_t c=fork();

  if(c==0){
    df = open(myfifo2, O_RDONLY);
    read(df, &val, sizeof(val));
    close(df);
    val= val+10;
    df = open(myfifo2, O_WRONLY);
    write(df, &val, sizeof(val));
    fd = open(myfifo, O_WRONLY); //if i put this write first print works and program finishes
    write(fd, &val, sizeof(val));

      }
  if(c>0)
   {
    val=1;
    df = open(myfifo2, O_WRONLY); 
    write(df, &val, sizeof(val)); 
    fd = open(myfifo, O_RDONLY);
    read(fd, &val, sizeof(val));
    printf("val is %d \n",val);

        }
}

对子项的第一次读取会等待父项在fifo文件中写入val,然后将新的val写入此fifo文件中,然后将值写入第二个文本文件中。在父项的代码中读取会等待此过程因此,我想要的全部是父进程仅在子进程已在myfifo2文件中写入val后才执行打印。这就是我使用的第二个命名管道的目的。但是,此代码得到了卡住了,什么也没打印。我注意到,如果我改变子进程中两次写入的顺序,它可以工作,但不能满足我所需要的上述要求。为什么会这样,我该如何解决呢?

1 个答案:

答案 0 :(得分:2)

发生了什么

虽然命名管道 可以用于缓冲(如您所愿),但要依靠它来不阻塞程序(因为这就是您所需要的,死锁 )是一种非常糟糕的做法。

此外,它还带有一些警告:

  • 为了获得“缓冲”效果,需要打开管道的两端(man 7 fifo

      

    必须先在两端打开FIFO(读取和写入),然后才能传递数据。通常,打开FIFO块,直到另一端也打开。

  • 一旦管道达到其容量,写入最终将被阻塞。该大小取决于系统,但可以通过F_SETPIPE_SZ fcntl进行设置。而且:

      

    请注意,由于管道缓冲区的页面是             数据写入管道时使用的字节数             可写的字数可能小于标称大小,具体取决于             取决于写入的大小。

因此,您遇到这种情况:

  • 父项(可能甚至可能还没有)在read上的/tmp/myfifo中等待。

  • /tmp/myfifo2由父级WR_ONLY打开。

  • 子代调用df = open(myfifo2, O_WRONLY);,并以/tmp/myfifo2的身份打开WR_ONLY 。因此,打开了管道的读取端,因此调用了open块。

  • 死锁

要解决此问题,只需以读写方式 在子级中打开myfifo2

df = open(myfifo2, O_RDWR); // instead of df = open(myfifo2, O_WRONLY);

IMO,这种通信模式看起来有些奇怪(并且很难理解)。