Help - newbie playing with pipes

This is a discussion on Help - newbie playing with pipes within the C Programming forums, part of the General Programming Boards category; Hello
I have a very simple program to test pipes that gives segmentation fault and I have no idea why.
...

Hmm I'm sorry. Probably there is something I don't understand. The way I thought it worked was:

1. get a array with 2 int --> pipes
2. close one end on the father pipes[0] and the other on the son pipes[1]
3. now I have a one way pipe father writes at pipes[1] and the son can read (what the father wrote) ate pipes[0]

"pipe() creates a pipe, a unidirectional data channel that can be used
for interprocess communication. The array pipefd is used to return two
file descriptors referring to the ends of the pipe. pipefd[0] refers
to the read end of the pipe. pipefd[1] refers to the write end of the
pipe."

I think you have it backwards...the parent process should write to pipe[1] and the child process should read from pipe[0].

It is not necessary to close one end of the pipe, but that is how I learned it as well. A pipe when created basically writes to itself (i.e. write something to pipe[1] and it comes back out pipe[0]). When you do a fork(), the child gets a copy of the file descriptors in the parent (pipe[0] and pipe[1]). If the parent is only going to be doing the writing, and no reading, then why not close pipe[0]?

The child has the same set of file descriptors, so whatever the parent sends down pipe[1] will pop back out the child's copy of pipe[0] -- closing pipe[0] in the parent has no effect on pipe[0] in the child. And likewise, if the child is only going to be reading, no hard in closing the write end of the pipe.

Also (maybe this helps clear up the picture), if you want true bidirectional communication, then you will need to create two pipes before you fork(). If you didn't do that - that is both parent and child only had pipe[0] and pipe[1], then both parent and child would have to read every message either of them sent. Anything that either of them writes down their copy of pipe[1] ends up in both of their copies of pipe[0].

EDIT: And i just realized that I've been reversing who is doing what in your code...so just swap parent and child in all my posts. In your example the child is doing the writing and the parent is reading, but the explanation remains the same.

After creating the pipe and before writing to it connect stdout to the write end of the file descriptor returned by the pipe() call. Same goes for the read end of the fd.
The code that writes to the pipe closes its read fd as in pipes[0] and the code that reads closes its write fd as in pipes[1]. Stripped down version of your code is posted here.

This code works just as well if you take out the dup2() calls. Every program has three open file descriptors to start with, descriptors 0, 1, and 2, which are for stdin, stdout, and stderr. The line,

Code:

dup2(pipes[1], 1);

is replacing stdout with the file descriptor of pipes[1]. That way, sending anything to stdout sends it down the pipe, rather than the terminal for example.

Likewise,

Code:

dup2(pipes[0], 0);

is replacing stdin with pipes[0]. Now anything read from stdin will be read out of the pipe.

This is an optional practice and may save a couple key strokes, but the code above doesn't make use of this, because it still passes pipes[1] and pipes[0] to write() and read(). To make use of the dup2() call, you can change the write() line to something like,

Code:

printf("%s", str);

Similarly, you can do something with that read call like

Code:

scanf("%100s", &res);

Note this isn't perfect since the %s conversion will stop at whitespace...so on the first read it will only pick up "hello". To get "world" you'll need to call it again.

This also allows you to just change the file descriptors you use in your read() and write() calls from pipes[0] to 0 and pipes[1] to 1, but then why bother?