We have discussed the nature and generation of processes. In the previous chapter we addressed primitive techniques for communicating between two or more processes. These techniques were limited in scope and suffered from a lack of reliable synchronization. Beginning with this chapter, we explore interprocess communication techniques using system-designed interprocess facilities. We start with pipes , which provide processes with a simple, synchronized way of passing information. By the early 1970s pipes became a standard part of UNIX.
We can think of the pipe as a special file that can store a limited amount of data in a first in, first out (FIFO) manner. On most systems, pipes are limited to a specific size . In Linux, the defined constant PIPE_SIZE (which is usually equivalent to the PAGE_SIZE for the system) establishes the total number of bytes allocated for a pipe. The defined constant PIPE_BUF (found in , which is included by ) sets the block size for an atomic write to a pipe. On our system the value for PIPE_BUF is 4096. Generally, one process writes to the pipe (as if it were a file), while another process reads from the pipe.
As shown in Figure 5.1, conceptually we can envision the pipe as a conveyor belt composed of data blocks that are continuously filled at (written to) the "write end" and emptied (read) from the "read end." The system keeps track of the current location of the last read/write location. Data is written to one end of the pipe and read from the other. From an implementation standpoint, an actual file pointer (as associated with a regular file) is not defined for a pipe, and as such no seeking is supported.
Figure 5.1. Conceptual data access using a pipe.
The operating system provides the synchronization between the writing and reading processes. By default, if a writing process attempts to write to a full pipe, the system automatically blocks the process until the pipe is able to receive the data. Likewise, if a read is attempted on an empty pipe, the process blocks until data is available. In addition, the process blocks if a specified pipe has been opened for reading, but another process has not opened the pipe for writing.
In a program, data is written to the pipe using the unbuffered I/O write system call (Table 5.1).
Table 5.1. Summary of the write System Call.
Include File(s) |
Manual Section |
2 |
||
Summary |
ssize_t write(int fd, const void *buf, size_t count); |
|||
Return |
Success |
Failure |
Sets errno |
|
Number of bytes written |
-1 |
Yes |
Using the file descriptor specified by fd , the write system call attempts to write count bytes from the buffer referenced by buf . If the write system call is successful, the number of bytes actually written is returned. Otherwise, a 1 is returned and the global variable errno is set to indicate the nature of the error. As shown in Table 5.2, the number of ways in which write can fail is impressive indeed!
Table 5.2. write Error Messages.
# |
Constant |
perror Message |
Explanation |
---|---|---|---|
4 |
EINTR |
Interrupted system call |
Signal was caught during the system call. |
5 |
EIO |
I/O error |
Low-level I/O error while attempting read from or write to file system. |
6 |
ENXIO |
No such device or address |
O_NONBLOCK O_WRONLY is set, the named file is a FIFO, and no process has the file open for reading. |
9 |
EBADF |
Bad file descriptor |
fd is an invalid file descriptor or is not open for writing. |
11 |
EAGAIN |
Resource temporarily unavailable |
O_NDELAY or O_NONBLOCK is set and the file is currently locked by another process. System memory for raw I/O is temporarily insufficient. Attempted a write to pipe of count bytes, but less than count bytes is available. |
14 |
EFAULT |
Bad address |
buf references an illegal address. |
22 |
EINVAL |
Invalid argument |
fd associated with an object unsuitable for writing. |
27 |
EFBIG |
File too large |
Attempt to write to a file that exceeds the current system limits. |
28 |
ENOSPC |
No space left on device |
Device with file has run out of room. |
32 |
EPIPE |
Broken pipe |
Attempt to write to a pipe that is not opened for reading on one end (in this case a SIGPIPE signal also generated). Attempt to write to a FIFO that is not opened for reading on one end. Attempt to write to a pipe with only one end open. |
34 |
ERANGE |
Numerical result out of range |
count value is less than 0 or greater than system limit. |
35 |
EDEADLK |
Resource deadlock avoided |
The write system call would have gone to sleep generating a deadlock situation. |
37 |
ENOLCK |
No locks available |
Locking enabled, but region was previously locked. System lock table is full. |
63 |
ENOSR |
Out of streams resources |
Attempt to write to a stream, but insufficient stream memory is available. |
67 |
ENOLINK |
The link has been severed |
The buf value references a remote system that is no longer active. |
write s to a pipe are similar to those for a file except that
[1] While write may still work if the number of bytes is greater than PIPE_BUF, it is best to stay within this limitation to guarantee the integrity of data.
O_NONBLOCK |
O_NDELAY |
Value Returned |
---|---|---|
set |
clear |
1 |
clear |
set |
If both O_NONBLOCK and O_NDELAY flags are set, write will not block the process.
Data is read from the pipe using the unbuffered I/O read system call summarized in Table 5.3.
Table 5.3. Summary of the read System Call.
Include File(s) |
Manual Section |
2 |
||
Summary |
ssize_t read(int fd, void *buf, size_t count); |
|||
Return |
Success |
Failure |
Sets errno |
|
Number of bytes read |
-1 |
Yes |
The read system call reads count bytes from the open file associated with the file descriptor fd into the buffer referenced by buf . If the read call is successful, the number of bytes actually read is returned. If the number of bytes left in the pipe is less than count , the value returned by read will reflect this. When at the end of the file, a value of 0 is returned. If the read system call fails, a 1 is returned and the global variable errno is set. The values that errno may take when read fails are shown in Table 5.4.
Table 5.4. read Error Messages.
# |
Constant |
Perror Message |
Explanation |
---|---|---|---|
4 |
EINTR |
Interrupted system call |
Signal was caught during the system call. |
5 |
EIO |
I/O error |
Background process cannot read from its controlling terminal. |
6 |
ENXIO |
No such device or address |
File descriptor reference is invalid. |
9 |
EBADF |
Bad file descriptor |
fd is an invalid file or is not open for reading. |
11 |
EAGAIN |
Resource temporarily unavailable |
O_NDELAY or O_NONBLOCK is set, and the file is currently locked by another process. System memory for raw I/O is temporarily insufficient. O_NDELAY or O_NONBLOCK is set, but there is no data waiting to be read . |
14 |
EFAULT |
Bad address |
buf references an illegal address. |
22 |
EINVAL |
Invalid argument |
fd associated with an unsuitable object for reading. |
35 |
EDEADLK |
Resource deadlock avoided |
The read system call would have gone to sleep generating a deadlock situation. |
37 |
ENOLCK |
No locks available |
Locking enabled, but region was previously locked. System lock table is full. |
67 |
ENOLINK |
Link has been severed |
The buf value references a remote system that is no longer active. |
74 |
EBADMSG |
Not a data message |
Message to be read is not a data message. |
In other aspects, read s performed on a pipe are similar to those on a file except that
O_NONBLOCK |
O_NDELAY |
Value Returned |
---|---|---|
set |
clear |
1 |
clear |
set |
Pipes can be divided into two categories: unnamed pipes and named pipes. Unnamed pipes can be used only with related processes (e.g., parent/child or child/child) and exist only for as long as the processes using them exist. Named pipes actually exist as directory entries. As such, they have file access permissions and can be used with unrelated processes.
Programs and Processes
Processing Environment
Using Processes
Primitive Communications
Pipes
Message Queues
Semaphores
Shared Memory
Remote Procedure Calls
Sockets
Threads
Appendix A. Using Linux Manual Pages
Appendix B. UNIX Error Messages
Appendix C. RPC Syntax Diagrams
Appendix D. Profiling Programs