Code Comments
Programming Forum and web based access to our favorite programming groups.#include <stdio.h>
main()
{
int fd[2];
pipe(fd); /* a pipe is created: fd[0] for read; fd[1] for write
*/
if (fork() == 0) { /* 1st child - output redirection */
dup2(fd[1], 1); /* connect stdout to pipe */
close(fd[0]); /* close unneeded file descriptors */
close(fd[1]);
printf("\nThis is the write end of the pipe:\n");
fflush(stdout); /* write out the msg to terminal */
execl("/usr/bin/who", "who", (char *)0);
printf("\nDummy Text Line\n");
}
if (fork() == 0) { /* 2nd child - input redirection */
dup2(fd[0], 0); /* connect stdin to pipe */
close(fd[0]); /* close unneeded file descriptors */
close(fd[1]);
printf("\nThis is the read end of the pipe:\n");
execl("/bin/sort", "sort", (char *)0);
printf("\nDummy Text Line\n");
}
close(fd[0]); /* parent is taking it easy */
close(fd[1]);
printf("\nParent is terminating\n");
return(0);
/////
I am unable to understand
dup2(fd[1], 1); /* connect stdout to pipe */
close(fd[0]); /* close unneeded file descriptors */
close(fd[1]);
now when we are duplication fd[1] to stdout.... Then if we will close
it then what will happen..??
And what will be expected ouput!
Post Follow-up to this messageOn Mar 21, 3:35 pm, Sanchit <sanchitgupt...@gmail.com> wrote: > <snip c code> > ///// > > I am unable to understand > dup2(fd[1], 1); /* connect stdout to pipe */ > close(fd[0]); /* close unneeded file descriptors */ > close(fd[1]); > > now when we are duplication fd[1] to stdout.... Then if we will close > it then what will happen..?? > > And what will be expected ouput! When pipe is called, two anonymous files are created. One for reading and one for writing. The file descriptor fd[0] is for reading and fd[1] for writing. Everytime a dup() or a fork() is called, the descriptors are duplicated, however there are still only *2* files. A file ceases to be open when all descriptors (references) of it are closed(). Just closing a reference, I presume, only deallocates the entry in the process fd table. child fd[0] fd[1] child fd[0] fd[1] parent fd[0] fd[1] .------------. | out | in | '------------' Here you have a parent and two child processes. They both have the same two files open, one for reading and one for writing. The parent serves only to open the files and to fork() the children.
Post Follow-up to this messageOn Mar 21, 6:35 am, Sanchit <sanchitgupt...@gmail.com> wrote: > I am unable to understand > dup2(fd[1], 1); /* connect stdout to pipe */ > close(fd[0]); /* close unneeded file descriptors */ > close(fd[1]); > now when we are duplication fd[1] to stdout.... Then if we will close > it then what will happen..?? After the duplication, there are two file handles that refer to the same end of the same pipe. Then one of them is closed, leaving just one. The pipe itself will be destroyed when there are no references left to it. DS
Post Follow-up to this messageOn Mar 21, 11:28 pm, David Schwartz <dav...@webmaster.com> wrote: > On Mar 21, 6:35 am, Sanchit <sanchitgupt...@gmail.com> wrote: > > > After the duplication, there are two file handles that refer to the > same end of the same pipe. Then one of them is closed, leaving just > one. The pipe itself will be destroyed when there are no references > left to it. > > DS SO what will be expected output? Also here will buffering of printf will come in picture??
Post Follow-up to this messageOn Mar 22, 2:17 am, Sanchit <sanchitgupt...@gmail.com> wrote: > SO what will be expected output? The output of 'who' will pass to the input of 'sort' through the pipe. The pipe will go away when both processes terminate. The output of 'sort' will be left where it is. > Also here will buffering of printf > will come in picture?? That's a matter of the internal details of 'sort' and 'who'. These programs don't need to know or care that they're talking to a pipe. When 'who' terminates, its end of the pipe will close, causing 'sort' to read end-of-file. DS
Post Follow-up to this messageOn Mar 22, 4:15 pm, David Schwartz <dav...@webmaster.com> wrote: > On Mar 22, 2:17 am, Sanchit <sanchitgupt...@gmail.com> wrote: > > > The output of 'who' will pass to the input of 'sort' through the pipe. > The pipe will go away when both processes terminate. The output of > 'sort' will be left where it is. > > > That's a matter of the internal details of 'sort' and 'who'. These > programs don't need to know or care that they're talking to a pipe. > When 'who' terminates, its end of the pipe will close, causing 'sort' > to read end-of-file. > > DS Thanks.. But amabout following points. 1. We are duplicating fd[1] to stdout. So now whatever will be written on stdout.. will go to pipe??? Now if this happens all the statements which will get printed on screen should be input to sort thus all the statements should be sorted not only output of who. 2. If second child (the one which involves sort) is called first .. then there will be no input to it. Then what will happen --Sanchit
Post Follow-up to this messageOn Mar 22, 4:32 am, Sanchit <sanchitgupt...@gmail.com> wrote: > Thanks.. But amabout following points. > 1. We are duplicating fd[1] to stdout. So now whatever will be written > on stdout.. will go to pipe??? When the new process writes on its file descriptor 1, it will be writing to the pipe. File descriptor 1 now refers to the 'write' side of the pipe. > Now if this happens all the statements > which will get printed on screen should be input to sort thus all the > statements should be sorted not only output of who. Huh? No. The old file descriptor 1 is implicitly closed by the 'dup' operation and is replaced with a new descriptor that refers to the write side of the pipe. The old stdout is completely unaffected by this, other than that it loses a reference. > 2. If second child (the one which involves sort) is called first .. > then there will be no input to it. Then what will happen Type 'sort' at a shell prompt and what happens? The 'sort' program starts, and waits for input. The parent still has a reference to the other end of the pipe, so 'sort' will wait for something to write to it. The 'sort' command will keep reading input, waiting if necessary, until it gets an end-of-file or an error. DS
Post Follow-up to this messageOn Mar 21, 1:35 pm, Sanchit <sanchitgupt...@gmail.com> wrote:
> #include <stdio.h>
> main()
> {
> int fd[2];
>
> pipe(fd); /* a pipe is created: fd[0] for read; fd[1] for write */
You MUST check that pipe succeeded before continuing.
Checking error conditions is important, and I believe it
is an error in execl later that is causing your confusion.
>
> if (fork() == 0) { /* 1st child - output redirection */
> dup2(fd[1], 1); /* connect stdout to pipe */
Technically, this does not connect stdout to the pipe. Instead,
it closes the file descriptor underlying stdout, and then creates
a new file descriptor with the same value as the file descriptor
underlying stdout. It is generally a bad idea to manipulate
the file descriptors underlying a FILE *.
> close(fd[0]); /* close unneeded file descriptors */
> close(fd[1]);
> printf("\nThis is the write end of the pipe:\n");
> fflush(stdout); /* write out the msg to terminal */
This comment is wrong, and I believe gets to the
heart of your confusion. At this point, stdout has
absolutely nothing to do with a terminal. When you
called dup2, the file descriptor underlying stdout
was changed. STDOUT_FILENO now references
the write end of the pipe, and that pipe is NOT
a terminal. (You really should fclose(stdout)
before you call dup2, and not use stdout anymore.)
> execl("/usr/bin/who", "who", (char *)0);
> printf("\nDummy Text Line\n");
You do realize that this line should never be called
unless execl fails, right?
> }
>
> if (fork() == 0) { /* 2nd child - input redirection */
> dup2(fd[0], 0); /* connect stdin to pipe */
> close(fd[0]); /* close unneeded file descriptors */
> close(fd[1]);
> printf("\nThis is the read end of the pipe:\n");
> execl("/bin/sort", "sort", (char *)0);
> printf("\nDummy Text Line\n");
On my system, this printf is called. Which means that execl()
failed. For me, it failed because /bin/sort does not exist.
Presumably, you meant to invoke "/usr/bin/sort". There
are 2 things that could be changed here.
1) use execlp( "sort", ... ) instead of execl
2) Replace the dummy printf call with:
perror( "execl" ); _exit( EXIT_FAILURE );
My guess is that replacing /bin/sort with the correct
path may give you the output you want/expect.
Post Follow-up to this messageThanks David and Williams for your excellent explanation. But still i have one doubt. This may be related to printf which is involved in program. According to david "At this point, stdout has absolutely nothing to do with a terminal. When you called dup2, the file descriptor underlying stdout was changed. STDOUT_FILENO now references the write end of the pipe, and that pipe is NOT a terminal. " Then this means whatever is written on stdout goes to pipe? If yes then printf output should go to stdout... And when you say STDOUT_FILENO references to write end of pipe does these means that whatever we write to stdout will go to pipe!
Post Follow-up to this messageOn Mar 22, 7:22 am, Sanchit <sanchitgupt...@gmail.com> wrote: > "At this point, stdout has > absolutely nothing to do with a terminal. When you > called dup2, the file descriptor underlying stdout > was changed. STDOUT_FILENO now references > the write end of the pipe, and that pipe is NOT > a terminal. " > Then this means whatever is written on stdout goes to pipe? Yes, if written by the process that performed the redirect. Other processes are not affected. > If yes then printf output should go to stdout... Correct. > And when you say STDOUT_FILENO references to write end of pipe does > these means that whatever we write to stdout will go to pipe! Yes. Again, only for that process. DS
Post Follow-up to this message
Show a Printable Version
Email This Page to Someone!
Receive updates to this thread
Powered by vBulletin
Copyright 2000-2006 Jelsoft Enterprises Limited.