• A pipe is a communication device that permits
unidirectional communication.
• Data is written to the “write end” of the pipe and is
read back from the “read end.”
• Pipes are serial devices; the data is always read from
the pipe in the same order it was written.
• Typically, a pipe is used to communicate between two
threads in a single process or between parent and child processes.
• In a shell, the symbol “| “creates a pipe.
• For example, this shell command causes the shell to produce
two child processes, one for ls and one for less:
• $ ls | less
– The shell also creates a pipe connecting the standard
output of the “ls” subprocess with the standard input of the “less” process.
– The filenames listed by “ls” are sent to “less” in
exactly the same order as if they were sent directly to the terminal.
• A pipe’s data capacity is limited. If the writer
process writes faster than the reader process consumes the data, and if the
pipe cannot store more data, the writer process blocks until more capacity
becomes available.
• If the reader tries to read but no data is available,
it blocks until data becomes available. Thus, the pipe automatically
synchronizes the two processes
• To create a pipe, invoke the “pipe” command.
• Synonpsis
– #include <unistd.h>
– int pipe(int pipefd[2]);
– Supply an integer array of size 2. The array is used
to return two file descriptors referring to ends of the pipe
– The call to pipe stores the reading file descriptor in
array position 0 and the writing file descriptor in position 1.
– For example, consider this code:
int pipe_fds[2];
int read_fd;
int write_fd;
pipe (pipe_fds);
read_fd = pipe_fds[0];
write_fd = pipe_fds[1];
Communication between Parent
and Child Processes
• A call to pipe creates file descriptors, which are
valid only within that process and its children.
• A process’s file descriptors cannot be passed to
unrelated processes; however, when the process calls fork, file descriptors are
copied to the new child process.
• Thus, pipes can connect only related processes
Example: The parent writes the string contained in the program's command-line argument to the pipe, and the child reads this string a byte at a time from the pipe and echoes it on standard output.
#include <sys/wait.h>
#include <stdio.h>
#include
<stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[]) {
int pipefd[2];
pid_t
cpid;
char
buf;
if
(argc != 2) {
exit(EXIT_FAILURE);
}
if
(pipe(pipefd) == -1) {
exit(EXIT_FAILURE);
}
cpid =
fork();
if
(cpid == -1) {
exit(EXIT_FAILURE);
}
if (cpid == 0) {
/* Child reads from pipe */
close(pipefd[1]);
// Close unused write end
while
(read(pipefd[0], &buf, 1) > 0) write(STDOUT_FILENO,
&buf, 1);
close(pipefd[0]);
exit(EXIT_SUCCESS);
}
else { /* Parent writes argv[1] to pipe */
close(pipefd[0]);
/* Close unused read end */
write(pipefd[1],
argv[1], strlen(argv[1]));
close(pipefd[1]);
wait(NULL);
/* Wait for child */ exit(EXIT_SUCCESS); } }
No comments:
Post a Comment