5.3.1Pipes
Pipes allow the transfer of data in a FIFO manner. The pipe() system call creates unnamed pipes. Unnamed pipes are only accessible to the creating process and its descendants through file descriptors. Once a pipe is created, a process may use the read() and write() VFS system calls to access it.
In order to allow access from the VFS layer, the kernel creates an inode object and two file objects for each pipe. One file object is used for reading (reader) and the other for writing (writer). It is the responsibility of the process to use the appropriate file descriptor for reading and writing. Processes access unnamed pipes through their VFS file descriptors. Hence, access control is performed at the VFS layer in the same manner as for regular files, as described in Sections 5.1.5.
The internal implementation of pipes has changed with the 2.6 kernel. Before, a pipe used a single page to buffer data between the file object reader and writer. For a process writing more than a single page, it became blocked until the file object reader consumed the amount of data necessary to allow the rest to be fit in the buffer. In the new implementation, known as circular pipes, a circular buffer is used.
Figure 5-15: Pipes Implementation
In a simple scenario, a curbuf pointer indicates the first buffer that contains data in the array, and nrbufs indicates the number of buffers that contain data. The page structures are allocated and used as necessary. In order to serialize access, the pipe semaphore is used, since file object writers and readers are able to manipulate nrbufs. Length and offset fields compose the pipe buffer structure in order for each entry in the circular buffer to be able to contain less than a full page of data.
This circular implementation improves pipe bandwidth from 30% to 90%, with a small increase in latency because pages are allocated when data passes through the pipe. The better results in performance are attributable to the large buffering, since file object readers and writers block less often when passing data through the pipe.
This new functionality implemented in circular pipes is intended to become a general mechanism for transmitting data streams through the kernel.
5.3.1.1Data structures and algorithms
The inode object refers to a pipe with its i_pipe field, which points to a pipe_inode_info structure. The pipe() system call invokes do_pipe() to create a pipe. The read() and write() operations performed on the appropriate pipe file descriptors invoke, through the file operations vector f_op of the file object, the pipe_read() and pipe_write() routines, respectively.
62