Thread: Help - newbie playing with pipes

  1. #1
    Registered User
    Join Date
    Apr 2008
    Posts
    101

    Question Help - newbie playing with pipes

    Hello

    I have a very simple program to test pipes that gives segmentation fault and I have no idea why.

    I have searched google and this forum but nothing.

    Code:
    #include <stdio.h> 
    #include <stdlib.h> 
    #include <unistd.h> 
    #include <sys/wait.h> 
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <signal.h>
    
    void worker(int fd_read, int fd_write, char* filename);
    
    int main (void) { 
    	//com_pipes pipes;
    	int pipes[2];
    	int flag = 0;
    	int res = -1;
    	int pid;
    	
    	pipe(pipes);
    	
    	pid = fork();
    	
    	if(pid == 0)
    	{	// FILHOS
    		printf("[Filhote %d]: O pai %d pediu-me para pesquisar o ficheiro %s .\n", getpid(), getppid(), "cenas");
    		close(pipes[1]);
    		
    		write(pipes[0], &flag, sizeof(int));
    		exit(0);
    	}
    	
    	close(pipes[0]);
    	read(pipes[1], &res, sizeof(int));
    	printf("Vou procurar o %s.\n", res);
    	
    	
    }
    Thanks in advanced

  2. #2
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    You really shouldn't play with pipes. You just may end up getting forked. No, these lame jokes never get old to me.

    Anyway, you close the pipe! What did you expect to happen?

  3. #3
    Registered User
    Join Date
    Apr 2008
    Posts
    101
    I closed one end of the pipe. That's what you're supposed to do right?

    Close one end on the father and the other on the son.

  4. #4
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    Yeah. But then you never set it to anything different. So it only has one "end" so to speak.

  5. #5
    Registered User
    Join Date
    Apr 2008
    Posts
    101
    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]

    Is this wrong or right?

  6. #6
    Registered User
    Join Date
    May 2008
    Posts
    87
    Your procedure is more or less correct, however,

    from the pipe manual page:

    "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].

    Give that a shot,

    Jason

  7. #7
    Registered User
    Join Date
    Apr 2008
    Posts
    101
    Thanks but doesn't work

    If anybody can figure this out, please help

  8. #8
    Registered User
    Join Date
    May 2008
    Posts
    87
    I copied your code, changed the end of the pipe you close as well as which you use to read to / write from and I believe your code is working.

    I also changed your printf to
    Code:
    printf("Vou procurar o %d.\n", res);
    since res is an integer. Changing setting flag = 1 and running, I get this output:

    jason@compy ~ $ ./pipetest2
    [Filhote 2309]: O pai 2308 pediu-me para pesquisar o ficheiro cenas .
    Vou procurar o 1.

  9. #9
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    Here is an example I just grabbed off of google. Notice how they don't close the pipe they are trying to use -_-

    Code:
        #include <stdio.h>
        #include <stdlib.h>
        #include <sys/types.h>
        #include <unistd.h>
    
        int main()
        {
            int pfds[2];
            char buf[30];
    
            pipe(pfds);
    
            if (!fork()) {
                printf(" CHILD: writing to the pipe\n");
                write(pfds[1], "test", 5);
                printf(" CHILD: exiting\n");
                exit(0);
            } else {
                printf("PARENT: reading from pipe\n");
                read(pfds[0], buf, 5);
                printf("PARENT: read \"%s\"\n", buf);
                wait(NULL);
            }
        }

  10. #10
    Registered User
    Join Date
    May 2008
    Posts
    87
    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].

  11. #11
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    I find that popen() does the trick 9 times out of 10.

  12. #12
    Registered User
    Join Date
    May 2008
    Posts
    87
    Also note that the example provided above is from Beej's Guide to Unix IPC, and the very next example does close the unused ends of the pipes, although he doesn't say why.

    http://beej.us/guide/bgipc/output/ht....html#pipefork

    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.
    Last edited by jason_m; 10-20-2008 at 06:36 PM.

  13. #13
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    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.
    Code:
    #include <stdio.h>
    #include <unistd.h>
    
    int main (void)
    {
        int pipes[2];
        char str[] = "hello world";
        char res[100];
        int pid;
    
        pipe(pipes);
        pid = fork();
    
        if (!pid) /* this is the child */
        {
            printf("[Filhote %d]: O pai %d pediu-me para pesquisar o ficheiro %s .\n", getpid(), getppid(), "cenas");
            dup2(pipes[1], 1);                /* connect stdout to the write end of the fd */
            close(pipes[0]);                  /* close the read end of the pipe */
            write(pipes[1], str, sizeof str); /* write to the stdout of the pipe */
        }
        else /* this is the parent */
        {
            dup2(pipes[0], 0);               /* connect stdin to the read end of the fd */
            close(pipes[1]);                 /* close the write end of the pipe */
            read(pipes[0], res, sizeof res); /* read from the stdin of the pipe */
            printf("Vou procurar o %s.\n", res);
        }
    }
    P.S. Avoid using variable or array names that are similar to system calls.

  14. #14
    Registered User
    Join Date
    May 2008
    Posts
    87
    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?

  15. #15
    Registered User
    Join Date
    Apr 2008
    Posts
    101
    Uau!

    Thanks for all the replies.

    I found out the problem was that you always have to read from pipes[0] and write to pipes[1]

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Pipes sometimes fail
    By EVOEx in forum Linux Programming
    Replies: 2
    Last Post: 05-02-2009, 01:47 PM
  2. Pipes, inheritence and some newbie questions
    By grasshopa in forum C++ Programming
    Replies: 2
    Last Post: 02-28-2006, 07:00 AM
  3. Pipes, inheritence, newbie questions
    By grasshopa in forum Windows Programming
    Replies: 0
    Last Post: 02-28-2006, 06:17 AM
  4. Services and Pipes
    By nickname_changed in forum Windows Programming
    Replies: 0
    Last Post: 07-16-2003, 06:46 AM
  5. Newbie Game Develpoers Unite!
    By Telenosis in forum Game Programming
    Replies: 10
    Last Post: 06-22-2002, 02:02 PM

Tags for this Thread