6.1 PipesThe capacity to communicate is essential for processes that cooperate to solve a problem. The simplest UNIX interprocess communication mechanism is the pipe, which is represented by a special file. The pipe function creates a communication buffer that the caller can access through the file descriptors fildes[0] and fildes[1]. The data written to fildes[1] can be read from fildes[0] on a first-in-first-out basis.
If successful, pipe returns 0. If unsuccessful, pipe returns 1 and sets errno. The following table lists the mandatory errors for pipe.
Example 6.1The following code segment creates a pipe.
If the pipe call executes successfully, the process can read from fd[0] and write to fd[1].A single process with a pipe is not very useful. Usually a parent process uses pipes to communicate with its children. Program 6.1 shows a simple program in which the parent creates a pipe before forking a child. The parent then writes a string to the pipe and prints a message to standard error. The child reads a message from the pipe and then prints to standard error. This program does not check for errors on the read or write operations. Program 6.1 parentwritepipe.cA program in which a parent writes a string to a pipe and the child reads the string. The program does not check for I/O errors.
Exercise 6.2Run Program 6.1 and explain the results. Does the child always read the full string?Answer:The parent's bufin always contains the string "empty". The child's bufin most likely contains the string "hello". However, reads from pipes are not atomic. That is, there is no guarantee that a single read call actually retrieves everything written by a single write call. It is possible (though not likely in this case) that the child's bufin could contain something like "helty" if read retrieves only partial results. If the parent's write operation fails, the child's bufin contains "empty". Exercise 6.3Consider the following code segment from Program 6.1.
What happens if you replace it with the following code?
(The copyfile function is shown in Program 4.6 on page 100.)Answer:The parent process reads from standard input and writes to the pipe, while the child reads from the pipe and echoes to standard output. The parent echoes everything entered at the keyboard as it is typed, and the child writes to the screen as it reads each entered line from the pipe. A difficulty arises, however, when you enter the end-of-file character (usually Ctrl-D) at the terminal. The parent detects the end of the input, displays the message written by its fprintf, and exits with no problem, closing its descriptors to the pipe. Unfortunately, the child still has fd[1] open, so the copyfile function does not detect that input has ended. The child hangs, waiting for input, and does not exit. Since the parent has exited, the prompt appears, but the child process is still running. Unless you execute ps you might think that the child terminated also. To fix the problem, replace the substitute code with the following.
Program 3.2 from page 68. The modification demonstrates how to use reading from pipes for synchronization. The parent creates a pipe before creating n-1 children. After creating all its children, the parent writes n characters to the pipe. Each process, including the parent, reads a character from the pipe before proceeding to output its information to standard error. Since the read from the pipe blocks until there is something to read, each child waits until the parent writes to the pipe, thereby providing a synchronization point called a barrier. None of the processes can do any writing to standard error until all of the processes have been created. Section 6.8 gives another example of barrier synchronization. Notice that Program 6.2 uses r_write and r_read rather than write and read to ensure that the parent actually writes everything and that the children actually perform their reads. The children do not synchronize after the barrier. Program 6.2 synchronizefan.cA synchronized process fan. Processes wait until all have been created before echoing their messages to standard error.
|