Shouldn't UNIX pipes be unidirectional?

Take a look at the following code:

#include<unistd.h> #include<stdlib.h> #include<stdio.h> #include<string.h> #include<sys/types.h> main() { int pipdes[2]; char buff[50]; const char parent[]="Parent Writes. Child Reads\n"; const char child[]="Child Writes. Parent Reads\n"; if(pipe(pipdes)==0) { pid_t pid=fork(); if(pid<0) printf("Error\n"); if(pid==0){ read(pipdes[0],buff,50); printf("Parent: %s",buff); write(pipdes[1], child, strlen(child)); exit(0); } else if(pid>0) { write(pipdes[1], parent, strlen(parent)); wait(pid); read(pipdes[0], buff, 50); printf("Child: %s", buff); } } else printf("Error in pipe\n"); } 

Now I have created only one channel, but both processes can read and write. Should pipes not be unidirectional. In addition, when I put the usual “close (pipdes [0])” for the parent and “close (pipdes [1])” for the child, the code does not work, although I add the open (pipdes [0]) function later.

My concepts with UNIX and pipe have not been processed yet, so I might be a little mistaken, but please help.

+7
source share
3 answers

In some systems, pipes may be bi-directional. But they should not be, and any assumption that they will not be tolerated. In particular, they are not on Linux.

Be that as it may, your code has a problem - both processes try to read and write to the same channel. The intended use for pipes is what the child writes and the parent reads, or vice versa. The current way that you do all this works for you right now, because you read and write once and wait for the child. But when you execute a cycle trying to do what you are doing, you cannot wait - and without synchronization, the child will often (but not always!) End up reading what he intended to send to his parents, and vice versa.

If you need data going in both directions, you can use two pairs of pipes. Name them parent_pipe and child_pipe . The parent would read from parent_pipe[0] and write to child_pipe[1] , and the child would read from child_pipe[0] and write to parent_pipe[1] .

 #include<unistd.h> #include<stdlib.h> #include<stdio.h> #include<string.h> #include<sys/types.h> int main() { int parent_pipe[2]; int child_pipe[2]; char buff[50]; if(pipe(parent_pipe) || pipe(child_pipe)) { perror("pipe(...)"); exit(1); } // As noted elsewhere, you're using `fork()` incorrectly. // `fork()` returns 0 to the child, and a pid to the parent, or -1 if an error // occurs. int pid = fork(); if (pid == -1) { perror("fork()"); exit(1); } if (pid == 0) { // this is the child process. read from child_pipe, write to parent_pipe const char child[]="Child Writes. Parent Reads\n"; int in, out; in = child_pipe[0]; // in = parent_pipe[0]; // uncomment me to test with one pipe pair out = parent_pipe[1]; for (int i = 0; i < 10; ++i) { read(in,buff,50); printf("Parent: %s",buff); // NOTE: `strlen(child)` doesn't include the nul at the end! write(out, child, strlen(child) + 1); } } else { // this is the parent process const char parent[]="Parent Writes. Child Reads\n"; int in, out; in = parent_pipe[0]; out = child_pipe[1]; // out = parent_pipe[1]; // uncomment me to test with one pipe pair for (int i = 0; i < 10; ++i) { write(out, parent, strlen(parent) + 1); read(in, buff, 50); printf("Child: %s", buff); } } } 

Alternatively, you can use a pair of UNIX sockets created using socketpair(AF_LOCAL, SOCK_STREAM, 0, sockdes) (where sockdes is what we renamed pipdes to, since it is now sockets, not pipes). The child will read and write to sockdes[0] , and the parent will read and write to sockdes[1] . Or vice versa.

+18
source

In POSIX.1-2001, pipes are unidirectional. On the man page:

pipe () creates a pair of file descriptors, pointing to the inode index, and puts them in the array pointed to by filedes. filedes [0] for reading, filedes [1] for writing.

By the way, using fork is wrong: fork returns pid>0 for the parent and pid==0 for the child. pid<0 means that an error has occurred.

+5
source

No, it is not. There were some bidirectional pipe systems (Sun, IIRC). If you really need a bidirectional channel, you can use socketpair ().

+4
source

All Articles