written 6.9 years ago by | modified 2.9 years ago by |
Subject: Operating System
Topic: STORAGE MANAGEMENT
Difficulty: Medium
written 6.9 years ago by | modified 2.9 years ago by |
Subject: Operating System
Topic: STORAGE MANAGEMENT
Difficulty: Medium
written 6.7 years ago by | modified 6.7 years ago by |
Input/output (I/O) buffering is a mechanism that improves the throughput of input and output operations. It is implemented directly in hardware and the corresponding drivers and is also ubiquitous among programming language standard libraries.
I/O operations often have high latencies; the time between the initiation of an I/O process and its completion may be millions of processor clock cycles.
Most of this latency is due to the hardware itself; for example, information cannot be read from or written to a hard disk until the spinning of the disk brings the target sectors directly under the read/write head. When the input/output device is a network interface, the latency is usually greater yet.
This is alleviated by having one or more input and output buffers associated with each device. Even if a program only wants to read one block of data from a device, the driver might fetch that block plus several of the blocks immediately following it on the disk, caching these in memory, because programs often access the disk sequentially, meaning that the next block the program will request is likely the next physical block on the disk.
When it actually does, the driver, instead of performing another physical read on the disk, can then simply return that block, and hence reduce the latency dramatically.
When writes to disk are requested, the driver may simply cache the data in memory until it has accumulated enough blocks of data, at which point it writes them all at once; this is called flushing the output buffer, or syncing.
The driver will normally provide a means to request that data be flushed immediately, rather than cached. This must be done, for example, before the device is removed from the system or when the system is shutting down.
On a multitasking operating system, hardware devices are controlled by the kernel, and user space applications may not directly access them. For this reason, performing I/O requires performing system calls, which, for various reasons, introduce overhead. This overhead is typically on the order of microseconds rather than millisecond, so using buffering here is not crucial for programs that perform a relatively small amount of I/O, but makes a big difference for applications that are I/O bound.
Thus, nearly every program written in a high-level programming language will have its own I/O buffers. These buffers may be much larger than the ones maintained by the low-level drivers, and they exist at a higher level of abstraction, as they are associated with file handle or file descriptor objects rather than actual hardware.
Now, when a program wants to read from a file, it first checks whether anything is left in that file's input buffer; if so, it simply returns that, and only when the buffer is exhausted, does the program perform a system call to read more data from the file—often, more than is requested by the program at the current time.
Likewise, each output (write) routine simply tacks data onto the buffer, until it is filled, at which point its contents are sent to the system. This is all performed "behind-the-scenes" by the standard library's input and output routines, which again will usually expose some means to manually flush the output buffers.
The various I/O buffering techniques are as follows:
1. Single buffering:
When a user process issues an I/O request, the O.S assigns a buffer in the system portion of main memory to the operation.
In the block oriented devices, the techniques can be used as follows: Input transfers are made to the system buffer. When the transfer is complete, the process moves the block into user space and request another block. This is called reading ahead, it is done in the expectation that the block will be needed sometimes in future. This approach will generally provide a speed up compared to the lack of system buffering. The O.S must keep track of the assignment of system buffers to user processes.Similar considerations apply to block oriented output. When data are being transmitted to a device, they are first copied from user space into the system buffer, from which they will ultimately be written. The requesting process is now free to continue.
Suppose T is the time required to input one block and C is the computation time required for input request.
i. Without buffering: Execution time is T+C.
ii. Without buffering: Execution time is max [C, T] +M, where M is time required to move the data from system buffer to user memory.
In stream oriented I/O, it can be used in two ways,
a. Line-at a time fashion.
Line- at a time operation is used for scroll made terminals. User inputs one line at a time, with a carriage return signalling at the end of a line.
b. Byte-at a time fashion.
Byte-at a time operation is used on forms mode, terminals when each keystroke is significant.
2. Double buffering
An improvement over single buffering is by assigning two system buffers to the operations.
A process transfers data to one buffer while operating system empties the other as shown in fig.
For block oriented transfer execution time is Max[C,T]. It is possible to keep the block oriented device going at full speed.
i. If C<=T, i.e. computation time is less than the time required to input one block.
ii. If C>T, i.e. computation time is greater than the time required to input one block, then double buffering ensures that the process will not have to wait on I/O.
For Stream oriented input again two types.
For line- at a time I/O, the user process need not be suspended for input or output, unless process runs ahead of double buffer.
For byte- at a time operations, double buffer offers no advantage over a single buffer of twice the length.
3. Circular buffer
Double buffering may be inadequate, if the process performs rapid burst of I/O. When two or more buffers are used.
The collection of buffers is called as a circular buffer, with each buffer being one unit in the circular buffer.