@harpsword
2015-11-04T12:44:22.000000Z
字数 2603
阅读 1955
操作系统
块设备
表1: linux/kernel/blk_drv 目录
文件名 | 大小 | 最后修改时间 |
---|---|---|
Makefile | 1951 bytes | 1991-12-05 19:59:42 |
blk.h | 3464 bytes | 1991-12-05 19:58:01 |
floppy.c | 11429 bytes | 1991-12-07 00:00:38 |
hd.c | 7807 bytes | 1991-12-05 19:58:17 |
ll_rw_blw.c | 3539 bytes | 1991-12-04 13:41:42 |
ramdisk.c | 2740 bytes | 1991-12-06 03:08:06 |
1. 对硬盘和软盘块设备上数据的读写操作是通过中断处理程序进行的
2. 每次读写的数据量以一个逻辑块(1 block = 1 KB = 1024 B)为单位。
3. 在处理过程中,使用了读写请求等待队列来顺序缓冲一次读写多个逻辑块的操作。
块设备表 blk_dev[] : 这是内核用来管理块设备的。每种块设备都在该表中占有一项。
struct blk_dev_struct {
void ( * request_fn) (void); // 某种块设备的请求项操作函数指针
struct request * current_request; // 当前请求项指针
}
extern struct blk_dev_struct blk_dev[NR_BLK_DEV]; // 块设备表(数组)(NR_BLK_DEV = 7)
主设备号 | 类型 | 说明 | 请求项操作 |
---|---|---|---|
0 | 无 | 无 | NULL |
1 | 块/字符 | ram,内存设备(虚拟盘等) | do_rd_request() |
2 | 块 | fd,软驱设备 | do_fd_request() |
3 | 块 | hd,硬盘设备 | do_hd_request() |
4 | 字符 | ttyx 设备 | NULL |
5 | 字符 | tty设备 | NULL |
6 | 字符 | lp打印机设备 | NULl |
ll_rw_block()函数简介:当内核发出一个块设备读写或者其他操作请求时,ll_rw_block()函数即会根据其参数中指明的操作命令和数据缓冲块头中的设备号,利用对应的 请求项操作函数do_XX_request() 建立一个 块设备请求项 ,并利用 电梯算法 插入到请求队列中去。 请求项队列 由请求项数组中的项构成, 共有 32 项。 如下是每个请求项的数据结构
struct request{
int dev; // 使用的设备号 (若为 -1 ,表示该项空闲)
int cmd; // 命令(READ 或者 WRITE)
int errrors; // 操作时产生的错误次数
unsigned long sector; // 起始扇区 (1块 = 2 扇区)
unsigned long nr_sectors; // 读/写扇区数
char * buffer;; // 数据缓冲区
struct task_struct * waiting; // 任务等待操作执行完成的地方
struct buffer_head *bh; // 缓冲区头指针(include/linux/fs.h,68)
struct request * next; // 指向下一项请求项
};
extern struct request request[NR_REQUEST]; // 请求队列数组(NR_REQUEST = 32)
请求项采用数组加链表结构的主要原因是
另外:为了满足读操作的优先权,在建立新的请求项而搜索请求项数组时,把建立写操作时的空闲项搜索范围限制在整个请求项数组的前 2/3 范围内, 而剩下的 1/3 请求项专门给读操作建立请求项使用。
ll_rw_block() 具体实现 : 对于一个当前空闲的块设备,当ll_rw_block()函数为其建立第一个请求项时,会让该设备的当前请求项指针current_request直接指向刚建立的请求项,并且理科调用对应设备的请求项操作函数开始执行块设备读写操作。当一个块设备已经有几个请求项组成的链表存在,ll_rw_block()就会利用电梯算法,根据磁头移动距离最小原则,把新建的请求项插入到链表中适当的位置。
由于它的读写操作不牵涉到与外部设备之间的同步操作,因此没有上述的中断处理过程。当前请求项对虚拟设备的读写操作完全在do_rd_requst()中实现。