Let’s take a look at I/O management in Linux.

Linux and other UNIX systems, I/O management is straightforward and simple. All IO devices are treated as files, which are read and written internally using the same read and write.

Basic Concepts of Linux IO

Linux also has I/O devices such as disks, printers, and networks, which Linux incorporates into the file system as a special file, usually located in the /dev directory. These special files can be treated in the same way as regular files.

Special files generally fall into two categories:

A block special file is a device capable of storing fixed-size chunks of information that can be read and (optionally) written to fixed-size chunks, sectors, or clusters. Each block has its own physical address. Typically block sizes range from 512 to 65536. All information transmitted will be in contiguous chunks. The basic feature of a block device is that each block is opposite and can read and write independently. Common block devices are hard disks, Blu-ray discs, and USB disks. Block devices usually require fewer pins than character devices.

! [over, the hardware into essence, it turned out to bypass the CPU] (https://p1-tt.byteimg.com/origin/pgc-image/9ca7d93c41434d8aa2bbab20fab49ebe?from=pc)

Disadvantages of block-specific files Block devices based on a given solid-state memory are slower than byte addressing based on the same type of memory because reading or writing must begin at the beginning of the block. So, to read any part of the block, you must find the beginning of the block, read the whole block, and discard it if it is not used. To write part of a block, you have to find the beginning of the block, read the whole block into memory, modify the data, find the beginning of the block again, and then write the whole block back to the device.

Another class of I/O devices are character special files. The character device sends or receives a stream of characters in units of characters, regardless of any block structure. The character device is not addressable and does not have any seek operations. Common character devices are printers, network devices, mice, and most other devices that are different from disks.

! [over, the hardware into essence, it turned out to bypass the CPU] (https://p3-tt.byteimg.com/origin/pgc-image/d2eeb914ca2943a981668078ed0835b3?from=pc)

Each device-specific file is associated with the device driver. Each driver is identified by a major device number. If a driver supports multiple devices, a secondary device number is added after the primary device to identify the driver. The primary and secondary device numbers together identify the unique driver device.

As we know, in a computer system, the CPU does not directly interact with the Device, but has a component called Device Control Unit in between. For example, the hard disk has a disk controller, the USB has a USB controller, and the monitor has a video controller. These controllers are like agents, they know how to deal with the behavior of hard drives, mice, keyboards and monitors.

Most character special files cannot be accessed randomly because they need to be controlled in a different way than block special files. For example, if you type some characters on the keyboard, but you find that you have typed a wrong one, some people like to use backspace to delete, others like to use del to delete. To interrupt a running device, some systems use Ctrl-U to end, but ctrl-C is now common.

network

Another concept of I/O is the network, also introduced by UNIX, and a key concept in the network is the socket. A socket allows a user to connect to the network, just as a mailbox allows a user to connect to the postal system, as shown in the diagram below

! [over, the hardware into essence, it turned out to bypass the CPU] (https://p1-tt.byteimg.com/origin/pgc-image/b7679e2a647b42f596c8543270804e64?from=pc)

Sockets are positioned as shown in the figure above and can be created and destroyed on the fly. After a socket is successfully created, the system returns a file descriptor. This file descriptor is used for creating links, reading data, writing data, and disconnecting connections. Each socket supports a specific type of network type, specified at creation time. The most commonly used ones

  • Reliable connection-oriented byte stream
  • Reliable connection-oriented packets
  • Unreliable packet transmission

A reliable connection-oriented bytecode uses pipes to establish a connection between two machines. Being able to ensure that bytes arrive sequentially from one machine to another, the system is able to guarantee that all bytes will arrive.

The second type is similar to the first except for the demarcation between packets. If three writes are sent, the recipient using the first method receives all bytes directly; The recipient of the second method receives all bytes in three installments. In addition, users can also use the third type of data packet transmission, which is unreliable. The advantage of using this transmission method is high performance, sometimes it is more important than reliability, such as in streaming media, performance is especially important.

The above involves two forms of transport protocol, NAMELY TCP and UDP. TCP is the Transmission control protocol, which can transmit reliable byte streams. UDP is a user datagram protocol that can only transmit unreliable byte streams. They all belong to the TCP/IP protocol cluster. The following is the network protocol layer

! [over, the hardware into essence, it turned out to bypass the CPU] (https://p1-tt.byteimg.com/origin/pgc-image/f5656bcf5eda41e79e4dead32915d0d2?from=pc)

Both TCP and UDP are located at the network layer, which is based on IP, the Internet protocol.

Once the socket is established on the source and destination computers, a link can be established between the two computers. When the communicating party uses the LISTEN system call on the local socket, it creates a buffer and blocks until the data arrives. The other party uses the CONNECT system call. If the other party accepts the CONNECT system call, the system establishes a connection between the two sockets.

Once a socket connection is established, it acts as a conduit from which a process can read and write data using the file descriptor of the local socket and close the connection when it is no longer needed using the close system call.

! [over, the hardware into essence, it turned out to bypass the CPU] (https://p1-tt.byteimg.com/origin/pgc-image/7ee43951d22c4f51b41cb50c0aedf51c?from=pc)

Linux I/O system call

Every I/O device in a Linux system has a special file associated with it. What is a special file?

In an operating system, a special file is a file associated with a hardware device in the file system. Special files are also called device files. The purpose of a special file is to expose the device as a file in the file system. Special files provide an excuse for hardware devices to access tools for file I/O. Because there are two types of devices, there are also two types of special files, namely character special files and block special files

For most I/O operations, only the appropriate files can be used and no special system calls are required. Then, sometimes some device-specific processing is required. Prior to POSIX, most UNIX systems had a system call called IOCtl, which was used to perform a large number of system calls. Over time, POSIX has cleaned up the iocTL functionality into separate function calls for terminal devices, which are now separate system calls.

Here are the system calls for a few management terminals

The system calls

describe

! [over, the hardware into essence, it turned out to bypass the CPU] (https://p6-tt.byteimg.com/origin/pgc-image/5e1ad4e2d58f43a39d70cfc47c877ab6?from=pc)

Linux IO implementation

IO in Linux is implemented through a series of device drivers, one for each device type. The device driver reserves ports for the operating system and hardware to mask differences between the operating system and hardware.

When a user accesses a special file, the file system provides the primary device number and secondary device number of the special file and determines whether it is a block-specific file or a character-specific file. The primary device number is used to identify the character device or the block device, and the secondary device number is used for parameter transfer.

Each driver has two parts: both are part of the Linux kernel, and both run in kernel mode. The top half runs in the caller context and interacts with the rest of Linux. The second half runs in the kernel context and interacts with the device. Drivers can invoke kernel procedures such as memory allocation, timer management, DMA control, and so on. Callable kernel functions are documented in the driver-kernel interface.

I/O implementation refers to the implementation of both character devices and block devices

Block device implementation

The goal of the special file I/O portion of the system that handles blocks is to keep the number of transfers as small as possible. To achieve this, the Linux system sets up a cache between the disk driver and the file system, as shown in the figure below

! [over, the hardware into essence, it turned out to bypass the CPU] (https://p6-tt.byteimg.com/origin/pgc-image/4fd7a0f604cc41978ef73252fcdfa093?from=pc)

Prior to Linux kernel 2.2, Linux systems maintained two caches: the page cache and the buffer cache, so files stored in one disk block could be stored in both caches. After version 2.2, the Linux kernel has only one unified cache. A Generic Block layer brings these together, enabling the necessary transitions between disks, data blocks, buffers, and data pages. So what is a common data block layer?

The common data block layer is part of a kernel that handles requests to all block devices in the system. Common data blocks mainly have the following functions

The data buffer is placed high in memory so that when the CPU accesses the data, the page is mapped to the kernel linear address and then unmapped

Zero copy mechanism is implemented so that disk data can be placed directly into user mode address space without first copying to kernel memory

Managing disk volumes treats multiple disk partitions on different block devices as one partition.

Take advantage of the latest advanced features of disk controllers, such as DMA, etc.

The cache is a powerful tool to improve system performance. No matter what purpose a data block is needed, the system searches for the data block in the cache first. If the data block is found, the system returns it directly, avoiding a disk access and greatly improving system performance.

If the page cache does not contain this block, the operating system will fetch the page from disk into memory and then read it into the cache for caching.

The cache supports both read and write operations. When a program writes back a block, it is first written to the cache rather than to the disk. The block is written to the cache when the cache in the disk reaches a certain number of values.

IO schedulers are used in Linux systems to ensure less repetitive head movement and thus less loss. The I/O scheduler sorts read and write operations on block devices and merges read and write requests. Linux has many variations of the scheduler to meet different work needs. The most basic Linux scheduler is based on the traditional Linux Elevator scheduler. The main workflow of the Linux elevator scheduler is sorting disk sector addresses and storing them in a two-way linked list. New requests will be inserted as linked lists. This method can effectively prevent the magnetic head from moving repeatedly. Because the elevator scheduler is prone to hunger. As a result, Linux has been modified to maintain two linked lists, with sorted reads and writes within the deadline. The default read operation takes 0.5 seconds, and the default write operation takes 5 seconds. If the list with the longest waiting time within the deadline is not served, it will be served first.

Character device implementation

Interacting with the character device is relatively simple. Because character devices generate and consume character streams, bytes of data, support for random access makes little sense. One exception is the use of new rules (line disciplines). A line rule can be associated with a terminal device, represented by the tty_struct structure, which represents the interpreter that exchanges data with the terminal device, and of course is part of the kernel. For example, line rules can edit lines, map carriage returns to line feeds, and other operations.

What are line rules?

A line rule is a layer in some UNIx-like systems. A terminal subsystem typically consists of three layers: an upper layer that provides a character device interface, a lower layer of hardware drivers that interact with hardware or pseudo-terminals, and a middle layer of rules that implement behavior common to the terminal devices.

! [over, the hardware into essence, it turned out to bypass the CPU] (https://p1-tt.byteimg.com/origin/pgc-image/8fe2c55bbb4f4f389b6926fb34ff92c4?from=pc)

Network device implementation

Network devices interact differently, although network devices also produce character streams because their asynchronous nature makes it difficult for them to integrate with other character devices on the same interface. Network device drivers generate many packets of data that reach user applications over network protocols.

Modules in Linux

UNIX device drivers are statically loaded into the kernel. Therefore, device drivers are loaded into memory whenever the system is started. With the advent of Linux on personal computers, this pattern of static links being used for a while after completion was broken. The number of I/O devices available on PCS has increased by an order of magnitude relative to the I/O devices available on minicomputers. Most users do not have the ability to add a new application, update device drivers, reconnect the kernel, and then install.

Linux addresses this problem by introducing a loadable module mechanism. Loadable is a block of code that is added to the kernel while the system is running.

When a module is loaded into the kernel, several things happen: First, the module is dynamically redeployed during the loading process. Second, the system checks whether the resources required by the program are available. If available, mark these resources as in use. Third, set up the desired interrupt vector. Fourth, update the driver conversion table to handle the new master device type. Finally, run the device driver.

Once this is done, the driver is installed, and other modern UNIX systems support loadable mechanisms.