banner
ShuWa

ShuWa

是进亦忧,退亦忧。然则何时而乐耶?
twitter

Device Management

Device Controllers#

To shield the differences between devices, each device has a component called a device controller, such as a hard disk controller for a hard disk and a video controller for a monitor.

There are three types of registers in a controller, namely the status register, command register, and data register, as shown in the figure below:

image

The functions of these three registers are as follows:

  • The data register is used for the CPU to write data that needs to be transmitted to the I/O device. For example, if the content to be printed is "Hello," the CPU needs to send an H character to the corresponding I/O device.
  • The command register is used for the CPU to send a command to the I/O device to perform input/output operations. After the task is completed, the status in the status register is marked as completed.
  • The status register is used to inform the CPU whether the device is currently working or has completed its work. If it is in a working state, any data or command sent by the CPU will be ignored until the previous work is completed and the status in the status register is marked as completed. Only then can the CPU send the next character and command.

The CPU controls the devices by reading and writing the registers in the device controller, which is more convenient and standardized than directly controlling the input/output devices.

In addition, input/output devices can be divided into two categories: block devices and character devices.

  • Block devices store data in fixed-sized blocks, each with its own address. Hard disks and USB devices are common block devices.
  • Character devices send or receive a stream of characters. Character devices are not addressable and do not have any seek operations. A mouse is a common character device.

Block devices usually transfer a large amount of data, so a readable and writable data buffer is set up in the controller.

  • When the CPU writes data to the controller's buffer, the data will only be sent to the device when the buffer has accumulated a certain amount.
  • When the CPU reads data from the controller's buffer, it needs to wait until the buffer has accumulated a certain amount before copying it to memory.

This is done to reduce frequent operations on the device.

How does the CPU communicate with the control registers and data buffers of the device? There are two methods:

  • Port I/O: Each control register is assigned an I/O port, and these registers can be operated using special assembly instructions, such as in/out-like instructions.
  • Memory-mapped I/O: All control registers are mapped to the memory space, allowing data buffers to be read and written just like reading and writing memory.

I/O Control Modes#

Using interrupts for frequently reading and writing data to disks is not friendly to the CPU, as it can be frequently interrupted, occupying a significant amount of CPU time. The solution to this problem for such devices is to use DMA (Direct Memory Access) functionality, which allows devices to independently transfer I/O data to memory without involving the CPU. To implement DMA functionality, hardware support from a "DMA controller" is required.

image

Device Drivers#

Although the device controller shields many details of the device, the usage patterns of registers and buffers in each device controller are different. Therefore, to shield the differences in "device controllers," device drivers are introduced.

The device controller does not belong to the scope of the operating system; it is hardware. The device driver, on the other hand, is part of the operating system. The kernel code of the operating system can use the interface of the device driver like calling local code. The device driver is code that is specific to the device controller. It sends instructions to manipulate the device controller and can then operate the device controller.

Although different device controllers have different functions, the device driver provides a unified interface to the operating system. This allows different device drivers to be integrated into the operating system in the same way.

As mentioned earlier, there are many things about interrupts. When a device completes a task, it sends an interrupt to notify the operating system. The operating system needs a place to handle this interrupt, which is in the device driver. It promptly responds to the interrupt request sent by the controller and calls the corresponding interrupt handler based on the type of the interrupt to handle it.

image

Generic Block Layer#

To minimize the impact of differences between block devices, Linux uses a unified generic block layer to manage different block devices.

The generic block layer is an abstraction layer between the file system and the disk driver. It has two main functions:

  • The first function is to provide a standard interface for file systems and applications to access block devices. It abstracts various different disk devices into a unified block device and provides a framework in the kernel to manage the drivers for these devices.
  • The second function is to queue I/O requests from file systems and applications, and then reorder the queue, merge requests, and perform I/O scheduling. The main purpose is to improve the efficiency of disk read and write operations.

Linux supports five I/O scheduling algorithms in memory:

  • No scheduling algorithm: No processing is performed on file system and application I/O. This algorithm is commonly used in virtual machine I/O, where disk I/O scheduling is handled by the physical machine system.
  • First-In-First-Out (FIFO) scheduling algorithm
  • Completely Fair Scheduling (CFS) algorithm: It maintains an I/O scheduling queue for each process and evenly distributes I/O requests for each process based on time slices.
  • Priority scheduling
  • Deadline scheduling algorithm: It creates separate I/O queues for read and write requests, which can improve the throughput of mechanical disks and ensure that requests with deadlines are processed first. It is suitable for scenarios with high I/O pressure, such as databases.

Storage System I/O Software Layers#

The I/O of the Linux storage system can be divided into three layers from top to bottom: the file system layer, the generic block layer, and the device layer. The hierarchical relationship of these three layers is shown in the following figure:

image

The functions of these three layers are as follows:

  • The file system layer, including the virtual file system and the specific implementation of other file systems, provides a standard interface for applications to access files and uses the generic block layer to store and manage disk data.
  • The generic block layer includes the I/O queue and I/O scheduler for block devices. It queues I/O requests from the file system and selects an I/O request using the I/O scheduler to send to the device layer.
  • The device layer includes hardware devices, device controllers, and device drivers. It is responsible for the physical I/O operations of the devices.

With the file system interface, devices can be operated like special files in Linux, not only through file system commands but also through application programs using read and write functions. Therefore, devices in Linux are just special files.

However, in addition to read and write operations, it is also necessary to check specific device functions and properties. Therefore, an ioctl interface is needed. It stands for input/output control interface and is a general interface for configuring and modifying specific device properties.

In addition, I/O is the slowest part of the entire system, so Linux provides various caching mechanisms to improve I/O efficiency.

  • To improve file access efficiency, various caching mechanisms such as page cache, inode cache, and directory entry cache are used to reduce direct calls to block devices.
  • To improve the access efficiency of block devices, a buffer is used to cache the data of block devices.

What Happens When a Letter is Typed on the Keyboard?#

image
The memory interface in the CPU communicates directly with the system bus, and the system bus is connected to an I/O bridge. On the other side of the I/O bridge, it is connected to the memory bus, allowing the CPU to communicate with the memory. On the other side, it is connected to an I/O bus used to connect I/O devices such as keyboards and displays.

When a user enters a character on the keyboard, the keyboard controller generates a scan code and stores it in the register of the keyboard controller. Then, the keyboard controller sends an interrupt request to the CPU via the bus.

After receiving the interrupt request, the operating system saves the CPU context of the interrupted process and calls the interrupt handler for the keyboard.

The interrupt handler for the keyboard is registered when the keyboard driver is initialized. The function of the interrupt handler for the keyboard is to read the scan code from the buffer of the keyboard controller's register and find the character entered by the user based on the scan code. If the entered character is a display character, the scan code will be translated into the corresponding ASCII code of the display character. For example, if the user enters the letter A on the keyboard, which is a display character, the scan code will be translated into the ASCII code of the letter A.

After obtaining the ASCII code of the display character, it is placed in the "read buffer queue." Next, the character needs to be displayed on the screen. The driver for the display device periodically reads data from the "read buffer queue" and puts the data into the "write buffer queue." Finally, the data in the "write buffer queue" is written to the data buffer of the display device's controller one by one, and the data is displayed on the screen.

After displaying the result, the interrupt handler restores the context of the interrupted process.

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.