块设备驱动程序
块设备驱动程序负责读写块设备数据。内核代码使用缓冲区块与块设备(如磁盘)间接交换数据,缓冲区数据通过块设备驱动程序和块设备交换。
[En]
The block device driver is responsible for reading and writing block device data. Kernel code uses buffer blocks to exchange data indirectly with block devices (such as disks), and buffer data is exchanged through block device drivers and block devices.
块设备的管理
块设备表
内核通过一张块设备表blk_dev[]管理各种块设备,每个表项对应一个块设备,并为每一个块设备维护一个请求队列。
- current_request:指向设备请求队列第一个节点,请求队列通过链表实现。
- request_fn:函数指针,用于处理请求队列里面的读写请求。
设备请求队列
内核为每个块设备维护一个请求队列,请求队列中请求等待被处理,current_request指向设备请求队列。
- 请求项
用于描述请求操作,包括读写磁盘扇区位置信息、缓冲区地址信息、操作类别(读写)信息等。
[En]
Used to describe the request operation, including read and write disk sector location information, buffer address information, operation category (read / write) information, etc.
请求项数据结构:
- 请求项数组
被分成请求项大小的块以形成充当内存池的数组的一段连续内存。请求队列中请求项的内存从请求项数组中分配,请求操作完成后,将请求项释放回内存池。
[En]
A piece of contiguous memory that is divided into blocks the size of a request item to form an array that acts as a memory pool. The memory of the request item in the request queue is allocated from the request item array, and after the request operation is completed, the request item is released back to the memory pool.
- 请求队列
在处理读写设备请求时,从请求项数组中获取空闲块,建立请求项,并将其插入到设备请求队列中。
[En]
When processing a read-write device request, get a free block from the request item array, establish the request item, and insert it into the device request queue.
块设备操作方式
在内核与块设备进行数据交换(IO)时,涉及到三个对象之间的交互作用,其中主要需要了解系统和控制器之间的交互过程。
- SYSTEM(内核):内核可以向控制器发送命令(发出请求),也可以等待设备控制器发出中断请求(完成请求)。
[En]
system (kernel): the kernel can send commands to the controller (make a request) or wait for the device controller to issue an interrupt request (complete request).*
- 控制器:完成读写操作后,向系统(CPU)发出中断。
- 驱动程序:由设备控制器控制
[En]
driver: controlled by device controller*
写数据过程
- 系统向控制器发出写命令后,等待块设备准备好接收数据,期间CPU需要主动查询控制器的状态寄存器判断是否准备好接收数据(忙等待)。
- 控制器准备好后,CPU将数据写入控制器的缓存中。(控制器具有一块缓存)
- 控制器将缓存中的数据通过驱动器全部写入块设备。
- 向CPU发出中断,中断处理程序完成写数据后的处理
读数据过程
- 向控制器发出读命令
- 控制器读取磁盘数据到其缓存中
- 向系统发起中断,中断处理程序从控制器缓存中取走数据
请求队列处理过程
ll_rw_block函数将请求放入块设备请求队列,设备中断处理程序会不断处理请求队列,直到队列为空。
-
*写请求的处理过程
-
ll_rw_block为写请求建立请求项,并插入设备的请求队列。 若插入前队列为空,则调用请求项操作函数(request_fn)处理当前写请求,对块设备进行写操作。
- 设备块设备完成一个写请求后,向CPU发出中断信号,CPU运行中断处理函数。
- 中断处理程序判断是否还有数据要写(一个请求会可能写多个扇区),如果有则继续写,然后等待下一次中断,这一过程重复直到该写请求数据全部写入设备。
- 完成数据写之后,中断处理程序将唤醒一些等待进程
- 唤醒等待该请求项有关数据的相关进程
- 唤醒等待请求项的进程(当内存池没有空闲请求项时,将导致某些请求读写的进程睡眠)
- 释放当前请求项并从链表中删除该请求项以及释放锁定的相关缓冲区。
-
唤醒等待进程后,中断处理程序将调用请求项操作函数处理下一个 读/写请求。
-
*读请求处理过程
与写请求处理过程类似
- *ll_rw_block与中断处理程序
ll_rw_block,负责将读写请求放入队列中,并 启动对请求队列的处理。
中断处理程序,在设备完成读写操作后,它发出中断并继续处理请求队列中的请求操作,直到请求队列为空。
[En]
Interrupt handler, after the device completes the read and write operation, it issues an interrupt and continues to process the request operation in the request queue until the request queue is empty.
相关知识
- I/O调度算法,读写请求不是按访问顺序放入请求队列的,0.11内核使用电梯算法调度读写请求
总结
- 每个块设备都有一个请求队列,对块设备的读写请求都会插入到队列中。
[En]
each block device has a request queue, and read and write requests to the block device are inserted into the queue.*
- 中断处理程序继续处理请求队列中的请求,直到队列为空。在请求完成后,一些等待的进程被唤醒。
[En]
the interrupt handler continues to process requests in the request queue until the queue is empty. After a request is completed, some waiting processes are awakened.*
Original: https://www.cnblogs.com/lazyfiish/p/16079465.html
Author: LazyFish
Title: Linux 0.11源码阅读笔记-块设备驱动程序
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/523920/
转载文章受原作者版权保护。转载请注明原作者出处!