overexchange overexchange - 1 month ago 10
C Question

How many file descriptors created/involved after running this program - pipe

From the below program,

/*****************************************************************************
MODULE: popen.c
*****************************************************************************/
#include <stdio.h>

int main(void)
{
FILE *pipein_fp, *pipeout_fp;
char readbuf[80];

/* Create one way pipe line with call to popen() */
if (( pipein_fp = popen("ls", "r")) == NULL)
{
perror("popen");
exit(1);
}

/* Create one way pipe line with call to popen() */
if (( pipeout_fp = popen("sort", "w")) == NULL)
{
perror("popen");
exit(1);
}

/* Processing loop */
while(fgets(readbuf, 80, pipein_fp))
fputs(readbuf, pipeout_fp);

/* Close the pipes */
pclose(pipein_fp);
pclose(pipeout_fp);

return(0);
}





popen.c
is compiled to
my_program


Here is my understanding of the file descriptors created/involved after executing
my_program
,
popen()
forks & execs the
my_program
process but child processes does not inherit the pipe file descriptors of
my_program
.

So, After exec,

1) write file descriptor is only created for
ls


2) read file descriptor is only created for
sort


3) read and write files descriptors are created in
my_program
, because
ls
writes to
my_program
&
sort
reads from
my_program


enter image description here




As shown above, Are these the only file descriptors involved/created?

Note: 'in' & 'out' are just naming conventions used here

Answer

Child processes from a fork() have exactly the same set of open file descriptors as the parent process.

The popen() call uses pipe() to create two file descriptors; it then executes fork(). The parent process arranges that one end of the pipe is closed and the other converted to a file stream (FILE *). The child process closes the other end of the pipe and arranges for the one end to become standard input ("w") or standard output ("r") for the process it executes (using dup() or dup2() for the task).

You use popen() twice; you end up with 2 open descriptors in the parent, and transiently there's a third.

  1. When you say, 'the parent process arranges that one end of the pipe is closed', do you mean read file descriptor (stdin)?

Depending on the mode argument to popen(), one of the two ends of the pipe in the parent is closed immediately; the other is closed by pclose(). The file descriptor is 'never' the one for standard input or standard output — you have to go through extraordinary gyrations to make it so that is one of the standard I/O channels.

  1. Do all process thru popen() make sure they dup() to make sure they use stdout & stdin?

Each pipe has a read end and a write end. Take popen("ls", "r"); your program reads from the ls process. It (popen()) creates a pipe and forks. In the child, the write end of the pipe is connected to stdout (dup2() or perhaps dup()), and the read end of the pipe is closed, before the command is executed. In the parent, the read end of the pipe is 'converted to' or 'attached to' a stream (fdopen(), more or less) and the write end of the pipe is closed. In the parent process, the pipe is never connected to either stdout or stdin.

In the child process, either standard input or standard output is connected to the pipe, depending on the mode argument to popen().

Comments