简体   繁体   中英

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:

#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?

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 )

    The FIFO must be opened on both ends (reading and writing) before data can be passed. Normally, opening the FIFO blocks until the other end is opened also.

  • 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 . 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/myfifo2 is opened WR_ONLY by parent.

  • child calls df = open(myfifo2, O_WRONLY); , opening /tmp/myfifo2 also as WR_ONLY . Thus the read end of the pipe is not opened, therefore the call to open blocks.

  • Deadlock .

To solve this, opening myfifo2 in the child as read-write should be sufficient.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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