/* * Simple two-process pipe. * * This is an example of the pipe() and dup() system calls. * * This process creates a pipe() and fork()s into two processes. * The parent writes a message into the writing half of the pipe(). * The child reads from the reading half of the pipe(). * * To compile this on Unix: cc -o simpipe thisfile.c * Compiled and linked output will be put in file "simpipe". * * -IAN! idallen@ncf.ca */ #include #include #include #include #include #define PIPE_MSG 1024 // max length of message in pipe int main( int argc, char **argv ){ int pid; // pid of forked child process ssize_t ret; // return value of system calls int fildes[2]; // two int's for the pipe file descriptors char buf[PIPE_MSG]; // buffer to hold the message bytes // create a pipe: two integer Unix file descriptors if( (ret=pipe(fildes)) != 0 ) { perror("creation of pipe failed"); exit(1); } // split into two processes: child (reader) and parent (writer) switch( pid=fork() ) { case -1: /* ERROR */ perror("fork failed"); exit(1); case 0: /* CHILD - reads pipe via stdin */ // close stdin (unit 0) // dup() the reading fildes of the pipe onto unit 0 // close both the fildes of the pipe // read from stdin (from the pipe now on unit 0) close(0); if( dup(fildes[0]) < 0 ){ perror("dup"); exit(1); } close(fildes[0]); close(fildes[1]); /* * At this point in the code, we could exec() another * program, and that program would read from the pipe * when it read from stdin. Instead, we just read * from stdin (from the pipe) ourselves. */ ret = read(0,buf,sizeof(buf)); switch(ret){ case -1: perror("child read from pipe failed"); exit(1); case 0: fprintf(stderr,"child got EOF from pipe\n"); exit(1); default: buf[ret] = '\0'; // NUL terminate the string in the buffer fprintf(stderr,"child read %d bytes from pipe: %s\n", ret, buf); exit(0); } /*NOTREACHED*/ default: /* PARENT - writes pipe via stdout */ // close stdout (unit 1) // dup() the writing fildes of the pipe onto unit 1 // close both the fildes of the pipe // write to stdout (to the pipe now on unit 1) close(1); if( dup(fildes[1]) < 0 ){ perror("dup"); exit(1); } close(fildes[0]); close(fildes[1]); /* * At this point in the code, we could exec() another * program, and that program would write to the pipe * when it wrote to stdout. Instead, we just write * to stdout ourselves. NOTE: Anything written to * stdout after this point goes into the pipe! If you * want to print status messages, write them to stderr * instead of stdout. (Don't use plain "printf()"!) */ strcpy(buf,"Hello, this is a message from the parent."); ret = write(1,buf,strlen(buf)); // NOTE: not NUL terminated! switch(ret){ case -1: perror("parent write to pipe failed"); exit(1); case 0: fprintf(stderr,"parent wrote nothing into pipe\n"); exit(1); default: fprintf(stderr,"parent wrote %d bytes into pipe\n", ret); exit(0); } /*NOTREACHED*/ } }