简体   繁体   English

在c中使用多个管道

[英]Using multiple pipes in c

I wan't to write a program that uses 2 pipes to pass values between parent and child process.Code: 我不会编写使用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);

        }
}

The first read of the child waits for parent to write val inside the fifo file.After that it writes a new val into this fifo file and afterwards writes a value into the second text file.The read in parent's code waits for this write to happen.So,all in all what i want is the parent process to execute the print only after the child process has written val in myfifo2 file.That is the purpose of the second named pipe i have used.However,this code gets stuck and prints nothing.I noticed that if i change the turn of the two write in child process it works but it does not satisfy the above thing i need.Why is this happening and how do i solve this? 第一次读取子级会等待父级在fifo文件中写入val,然后将新的val写入此fifo文件中,然后将值写入第二个文本文件中,在父级代码中的读取会等待此写入发生因此,总的来说,我想要的是父进程仅在子进程已在myfifo2文件中写入val之后才执行打印。这就是我使用的第二个命名管道的目的。但是,此代码被卡住并打印没什么。我注意到,如果我更改子进程中两次写入的转换,它可以工作,但不能满足我所需的上述要求。为什么会这样,我该如何解决呢?

What's happening 发生了什么

While named pipes can be used with buffering (as you intend them to), relying on it to not block your program (because that's what you have, a deadlock ) is a really bad practice. 虽然命名管道可以与缓冲一起使用(如您所愿),但依靠它不阻塞程序(因为这就是您的工作,所以会出现死锁 ),这是一个非常糟糕的做法。

Moreover, it comes with some caveats: 此外,它还带有一些警告:

  • In order to have that "buffering" effect, the both ends of the pipe need to be opened ( man 7 fifo ) 为了产生“缓冲”效果,需要打开管道的两端( man 7 fifo

    The FIFO must be opened on both ends (reading and writing) before data can be passed. 必须先在两端打开FIFO(读取和写入),然后才能传递数据。 Normally, opening the FIFO blocks until the other end is opened also. 通常,打开FIFO块,直到另一端也打开。

  • Writes will eventually block once the pipe reaches it capacity. 一旦管道达到其容量,写入将最终阻塞。 This size depends on the system but can be set via F_SETPIPE_SZ fcntl . 该大小取决于系统,但可以通过F_SETPIPE_SZ fcntl进行设置。 But also: 但是也:

    Note that because of the way the pages of the pipe buffer are employed when data is written to the pipe, the number of bytes that can be written may be less than the nominal size, depend‐ ing on the size of the writes. 请注意,由于在将数据写入管道时采用管道缓冲区页面的方式,取决于写入的大小,可以写入的字节数可能小于标称大小。

So, you have this situation: 因此,您有这种情况:

  • Parent (probably, could be even not yet there) waits in read on /tmp/myfifo . 父级(可能甚至还没有在那里)在/tmp/myfifo上等待read

  • /tmp/myfifo2 is opened WR_ONLY by parent. /tmp/myfifo2 WR_ONLY由父级打开WR_ONLY

  • child calls df = open(myfifo2, O_WRONLY); 子级调用df = open(myfifo2, O_WRONLY); , opening /tmp/myfifo2 also as WR_ONLY . WR_ONLY打开/tmp/myfifo2 WR_ONLY Thus the read end of the pipe is not opened, therefore the call to open blocks. 因此, 打开管道的读取端,因此调用了open块。

  • Deadlock . 死锁

To solve this, opening myfifo2 in the child as read-write should be sufficient. 为了解决这个问题,在子级中以读写方式打开myfifo2 应该足够了。

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

IMO this communication pattern looks a bit strange (and hard to understand), though. IMO,这种通信模式看起来有些奇怪(并且很难理解)。

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

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