Descriptor

Notice also that the value 0 is returned by the read( ) system call only if the pipe is empty and no process is currently using the file object associated with the pipe's write channel.

Table 19-2. Reading n bytes from a pipe

At least one writing process

No writing process

Blocking read

Nonblocking read

Pipe Size P

Sleeping writer

No sleeping writer

p = 0

Copy n bytes and return n, waiting for data when the pipe buffer is empty.

Wait for some data, copy it, and return its size.

Return -eagain.

Return 0.

0 < p < n

Copy p bytes and return p: bytes are left in the pipe buffer.

Al

Copy n bytes and return n: p-n bytes are left in the pipe buffer.

The function performs the following operations:

1. Acquires the i_sem semaphore of the inode.

2. Determines whether the pipe size, which is stored into the len field of the pipe_inode_info structure, is 0. In this case, determines whether the function must return or whether the process must be blocked while waiting until another process writes some data in the pipe (see Table 19-2). The type of I/O operation (blocking or nonblocking) is specified by the O nonblock flag in the f flags field of the file object. If the current process must be blocked, the function performs the following actions:

a. Adds 1 to the waiting_readers field of the pipe_inode_info structure.

b. Adds current to the wait queue of the pipe (the wait field of the pipe_inode_info structure).

c. Releases the inode semaphore.

d. Sets the process status to task_interruptible and invokes schedule( ).

e. Once awake, removes current from the wait queue, acquires again the i_sem inode semaphore, decrements the waiting_readers field, and then jumps back to Step 2.

3. Copies the requested number of bytes (or the number of available bytes, if the buffer size is too small) from the pipe's buffer to the user address space.

4. Updates the start and len fields of the pipe_inode_info structure.

5. Invokes wake_up_interruptible( ) to wake up all processes sleeping on the pipe's wait queue.

6. If not all requested bytes have been copied, there is at least one writing process currently sleeping (waiting_writers field greater than 0) and the read operation is nonblocking, so the function jumps back to Step 2.

7. Releases the i_sem semaphore of the inode.

8. Returns the number of bytes copied into the user address space. 19.1.5 Writing into a Pipe

A process wishing to put data into a pipe issues a write( ) system call, specifying the file descriptor for the writing end of the pipe. The kernel satisfies this request by invoking the write method of the proper file object; the corresponding entry in the write_pipe_fops table points to the pipe_write( ) function.

Table 19-3 summarizes the behavior, specified by the POSIX standard, of a write( ) system call that requested to write n bytes into a pipe having u unused bytes in its buffer. In particular, the standard requires that write operations involving a small number of bytes must be atomically executed. More precisely, if two or more processes are concurrently writing into a pipe, each write operation involving fewer than 4,096 bytes (the pipe buffer size) must finish without being interleaved with write operations of other processes to the same pipe. However, write operations involving more than 4,096 bytes may be nonatomic and may also force the calling process to sleep.

Table 19-3. Writing n bytes to a pipe

At least one reading process

Available buffer space u

Blocking write

Nonblocking write

No reading process

u<n —'■ 4096

Wait until n-u bytes are freed, copy n bytes, and return n.

Return -eagain.

Send sigpipe signal and return

EPIPE.

n>4096

Copy n bytes (waiting when necessary) and return n.

If u>0, copy u bytes and return u; else return -

EAGAIN.

u — n

Copy n bytes and return n.

Moreover, each write operation to a pipe must fail if the pipe does not have a reading process (that is, if the readers field of the pipe's inode object has the value 0). In this case, the kernel sends a sigpipe signal to the writing process and terminates the write( ) system call with the -epipe error code, which usually leads to the familiar "Broken pipe" message.

The pipe_write( ) function performs the following operations:

1. Acquires the i_sem semaphore of the inode.

2. Checks whether the pipe has at least one reading process. If not, it sends a sigpipe signal to the current process, releases the inode semaphore, and returns an -epipe value.

3. Checks whether the number of bytes to be written is within the pipe's buffer size:

a. If so, the write operation must be atomic. Therefore, checks whether the buffer has enough free space to store all bytes to be written.

b. Otherwise, if the number of bytes is greater than the buffer size, the operation can start as long as there is any free space at all. Therefore, the function checks for at least one free byte.

4. If the buffer does not have enough free space and the write operation is nonblocking, releases the inode semaphore and returns the -eagain error code.

5. If the buffer does not have enough free space and the write operation is blocking, performs the following actions:

a. Adds 1 to the waiting_writers field of the pipe_inode_info structure.

b. Adds current to the wait queue of the pipe (the wait field of the pipe_inode_info structure).

c. Releases the inode semaphore.

d. Sets the process status to task_interruptible and invokes schedule( ).

e. Once awake, removes current from the wait queue, again acquires the inode semaphore, decrements the waiting_writers field, and then jumps back to Step 5.

6. Now the pipe buffer has enough free space to either copy the requested number of bytes (if the write operation must be atomic) or copy at least one byte; notice that other writers cannot steal free space because this writer owns the inode semaphore. Copies the requested number of bytes (or the number of free bytes if the pipe size is too small) from the user address space to the pipe's buffer.

7. Wakes up all processes sleeping on the pipe's wait queue.

8. If the write operation was blocking and not all requested bytes were written in the pipe buffer, jumps back to Step 5. Notice that this case may occur only when the write operation is nonatomic; hence the current process remains blocked until one or more bytes of the pipe buffer are freed.

9. Releases the inode semaphore.

10. Returns the number of bytes written into the pipe's buffer.

I [email protected] RuBoard

4 previous

4 previous

Was this article helpful?

0 0

Post a comment