Introduction

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

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

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.

Категории