Pipes
Pipes are the oldest form of UNIX System IPC and are provided by all UNIX systems.
Pipes have two limitations.
- Historically, they have been half duplex (i.e., data flows in only one direction). Some systems now provide full-duplex pipes, but for maximum portability, we should never assume that this is the case.
- Pipes can be used only between processes that have a common ancestor. Normally, a pipe is created by a process, that process calls fork, and the pipe is used between the parent and the child.
We’ll see that FIFOs get around the second limitation, and that UNIX domain sockets get around both limitations.
Despite these limitations, half-duplex pipes are still the most commonly used form of IPC. Every time you type a sequence of commands in a pipeline for the shell to execute, the shell creates a separate process for each command and links the standard output of one process to the standard input of the next using a pipe.
Half-duplex pipe after fork
For a pipe from the parent to the child, the parent closes the read end of the pipe (fd[0]), and the child closes the write end (fd[1]).
A simplest demo, pipe between parent and child, the direction is parent -> child.
#include "apue.h"
void
test_half_duplex_pipe(void) {
int n;
int fd[2];
pid_t pid;
char line[MAXLINE];
if (pipe(fd) < 0) {
err_sys("pipe failed");
}
if ((pid = fork()) < 0) {
err_sys("fork faiked");
} else if (pid > 0) {
//parent
close(fd[0]);
write(fd[1], "hello world\n", 12);
} else {
//child
close(fd[1]);
n = read(fd[0], line, MAXLINE);
write(STDOUT_FILENO, line, n);
}
}
int
main(void) {
test_half_duplex_pipe();
exit(0);
}
Popen
Since a common operation is to create a pipe to another process to either read its output or send it input, the standard I/O library has historically provided the popen and pclose functions. These two functions handle all the dirty work that we’ve been doing
ourselves: creating a pipe, forking a child, closing the unused ends of the pipe, executing a shell to run the command, and waiting for the command to terminate.
FILE *popen(const char *cmdstring, const char *type);
int pclose(FILE *fp);
The function popen does a fork and exec to execute the cmdstring and returns a standard I/O file pointer. If type is "r", the file pointer is connected to the standard output of cmdstring , If type is "w", the file pointer is connected to the standard input of cmdstring.
The implementation of Popen is based on Pipe.