Link to home
Start Free TrialLog in
Avatar of sonic2000
sonic2000

asked on

simple pipe

I have got the below code and is working fine!!!
Example of running the below program is
$> ./a.out who less

Basically my code does the same as "who | less"

My Question
========
if I change
    if ( pid > 0 ){         /* parent will exec av[2]   */
to
    if ( pid == 0 ){         /* child will exec av[2]   */
then everything will go haywire!

Why?



/* pipe.c      
 *  * Demonstrates how to create a pipeline from one process to another
 *  * Takes two args, each a command, and connects
 *    av[1]'s output to input of av[2]
 *  * usage: pipe command1 command2
 *    effect: command1 | command2
 *  * Limitations: commands do not take arguments
 *  * uses execlp() since known number of args
 *  * Note: exchange child and parent and watch fun
 */
#include    <stdio.h>
#include    <unistd.h>

#define oops(m,x)   { perror(m); exit(x); }

main(int ac, char **av)
{
    int thepipe[2],         /* two file descriptors */
        newfd,              /* useful for pipes */
        pid;                /* and the pid      */

    if ( ac != 3 ){
        fprintf(stderr, "usage: pipe cmd1 cmd2\n");
        exit(1);
    }
    if ( pipe( thepipe ) == -1 )        /* get a pipe       */
        oops("Cannot get a pipe", 1);

    /* ------------------------------------------------------------ */
    /*  now we have a pipe, now let's get two processes     */

    if ( (pid = fork()) == -1 )         /* get a proc   */
        oops("Cannot fork", 2);

    /* ------------------------------------------------------------ */
    /*  Right Here, there are two processes         */
    /*             parent will read from pipe           */

    if ( pid > 0 ){         /* parent will exec av[2]   */
        close(thepipe[1]);  /* parent doesn't write to pipe */                                                              
                                                                                                                           
        if ( dup2(thepipe[0], 0) == -1 )                                                                                    
            oops("could not redirect stdin",3);                                                                            
                                                                                                                           
        close(thepipe[0]);  /* stdin is duped, close pipe   */                                                              
        execlp( av[2], av[2], NULL);                                                                                        
        oops(av[2], 4);                                                                                                    
    }                                                                                                                      
                                                                                                                           
    /*   child execs av[1] and writes into pipe         */                                                                  
                                                                                                                           
    close(thepipe[0]);      /* child doesn't read from pipe */                                                              
                                                                                                                           
    if ( dup2(thepipe[1], 1) == -1 )                                                                                        
        oops("could not redirect stdout", 4);                                                                              
                                                                                                                           
    close(thepipe[1]);      /* stdout is duped, close pipe  */                                                              
    execlp( av[1], av[1], NULL);                                                                                            
    oops(av[1], 5);                                                                                                        
}
Avatar of lynxlupodian
lynxlupodian

Why 0? I don't think any process has that PID. And certainly no process has a negative PID. And afaik, you can't specify which PID to get when forking(may be just my inferiror knowledge).
Avatar of sonic2000

ASKER

it is possible to get a pid == -1 if the fork is unsuccessful (at least what is told by man fork)..
FYI, the above code is taken from a book and I am just wonder why when I swap child and parent, the result is so different.
-1 is not the PID, but the exit status code of fork. ;)

Well, doing something as "less | who" doesn't make sense from the start.
if ( (pid = fork()) == -1 )         /* get a proc   */
        oops("Cannot fork", 2);


pid == -1 if fork returns -1 (unsuccessful). Of course I know the result is the fork() :)

>>Well, doing something as "less | who" doesn't make sense from the start.
I did not say the code is doing that. I said "who | less" if you were to run the program plus read my question :)



Do you have better input?
>>I did not say the code is doing that. I said "who | less" if you were to run the program plus read my question :)
Didn't you ask why it's strange if you reverse them?

I'm guessing it's strange since only who generates output and only less can get piped input. So you are trying to get data from a silent command and give it to a deaf one. :D
sorry..
i am actually trying to ask why "who" has to be handled by child. Why can't parent handle it?
Is it because child will run first and so "who" should be handled by child?
ASKER CERTIFIED SOLUTION
Avatar of lynxlupodian
lynxlupodian

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Can you tell what goes haywire ?

Does the program block, does it produce garbled output? What happens?

Because i feel (as you do) that this switch of roles of parent and child should be legal. The last comment from lynx.. is not pertinent to this situation, he is talking about shell piping, which is different from constructing  your own programmatic pipe. Even if the listener would run first, it would block on the attempt to read from the pipe thereby releasing the processor to execute the producer...