Consider reading a file from disk for a process:
- Determine device holding file
- Translate name to devise representation
- Physically read data from disk into the buffer
- Make data available to requesting process
- Return control to process
The following steps have described the lifecycle of a blocking read request:
- A process issues a blocking read() system call to a file descriptor of a file that has been opened previously.
- The system-call code in the kernel checks the parameters for correctness. In the case of input, if the data are already available in the buffer cache, the data are returned to the process and the I/O request is completed.
- Otherwise, a physical I/O needs to be performed, so the process is removed from the run queue and is placed on the wait queue for the device, and the I/O request is scheduled. Eventually, the I/O subsystem sends the request to the device driver. Depending on the operating system, the request is sent via a subroutine call or via an in-kernel message.
- The device driver allocates kernel buffer space to receive the data and schedules the I/O. Eventually, the driver sends commands to the device controller by writing into the device control registers.
- The device controller operates the device hardware to perform the data transfer.
- The driver may poll for status and data, or it may have set up a DMA transfer into kernel memory. We assume that the transfer is managed by a DMA controller, which generates an interrupt when the transfer completes.
- The correct interrupt handler receives the interrupt via the interrupt-vector table, stores any necessary data, signals the device driver, and returns from the interrupt.
- The device driver receives the signal, determines which I/O request completed, determines the request’s status, and signals the kernel I/O subsystem that the request has been completed.
- The kernel transfers data or returns codes to the address space of the requesting process and moves the process from the wait queue back to the ready queue.
- Moving the process to the ready queue unblocks the process. When the scheduler assigns the process to the CPU, the process resumes execution at the completion of the system call.