// !> A pipe between two programs [fv] #include #include #include #include #include #include #include #include int main(int argc, char **argv) { /* Open files after program starts: * 0: stdin * 1: stdout * 2: stderr */ int pipe_fd[2]; // create a pipe: // pipe_fd[0] is the _read_ end // pipe_fd[1] is the _write_ end assert(pipe(pipe_fd) != -1); /* Open files after pipe call: * 0: stdin * 1: stdout * 2: stderr * 3: pipe read end (pipe_fd[0]) * 4: pipe write end (pipe_fd[1]) */ int write_fd = pipe_fd[1]; int read_fd = pipe_fd[0]; printf("read: %d, write: %d\n", read_fd, write_fd); pid_t reading_child = fork(); assert(reading_child != -1); if (reading_child == 0) { /* Open files in reading_child: * 0: stdin * 1: stdout * 2: stderr * 3: pipe read end (pipe_fd[0] / read_fd) * 4: pipe write end (pipe_fd[1] / write_fd) */ // both parent and child share both ends, so we'll just close the end we // don't use close(pipe_fd[1]); /* Open files after closing write end: * 0: stdin * 1: stdout * 2: stderr * 3: pipe read end (pipe_fd[0] / read_fd) * 4: - */ // close stdin close(0); /* Open files after closing stdin: * 0: - * 1: stdout * 2: stderr * 3: pipe read end (pipe_fd[0] / read_fd) * 4: - */ // replace fd 0 with pipe_fd[0] / read_fd assert(dup(read_fd) == 0); /* Open files after dup: * 0: pipe read end (pipe_fd[0] / read_fd) * 1: stdout * 2: stderr * 3: pipe read end (pipe_fd[0] / read_fd) * 4: - */ printf("About to run sort...\n"); assert(-1 != execlp("sort", "sort", NULL)); // should never get here return 1; } int writing_child = fork(); assert(writing_child != -1); if (writing_child == 0) { /* Open files in writing_child: * 0: stdin * 1: stdout * 2: stderr * 3: pipe read end (pipe_fd[0] / read_fd) * 4: pipe write end (pipe_fd[1] / write_fd) */ close(read_fd); /* Open files after closing read end: * 0: stdin * 1: stdout * 2: stderr * 3: - * 4: pipe write end (pipe_fd[1] / write_fd) */ // close stdout close(1); /* Open files after closing stdout: * 0: stdin * 1: - * 2: stderr * 3: - * 4: pipe write end (pipe_fd[1] / write_fd) */ // replace stsdout with write end of pipe assert(dup(write_fd) == 1); /* Open files after dup: * 0: stdin * 1: pipe write end (pipe_fd[1] / write_fd) * 2: stderr * 3: - * 4: pipe write end (pipe_fd[1] / write_fd) */ // run: shuf -i 1-9 assert(-1 != execlp("shuf", "shuf", "-i", "1-9", NULL)); // should never get here close(pipe_fd[1]); close(1); return 1; } /* Open files in parent: * 0: stdin * 1: stdout * 2: stderr * 3: pipe read end (pipe_fd[0] / read_fd) * 4: pipe write end (pipe_fd[1] / write_fd) */ close(write_fd); close(read_fd); /* Open files in parent after closing both ends of the pipe: * 0: stdin * 1: stdout * 2: stderr * 3: - * 4: - */ // Wait for both children to finish wait(NULL); wait(NULL); return 0; }