关键词:块设备、gendisk、请求队列、request queue、bio、page cache、I/O 调度器、通用块层、文件系统、磁盘管理
块设备是可以被分成固定大小块(通常为512字节或4KB)进行读写的设备。与字符设备不同,块设备支持随机访问和缓存,是构建文件系统的基础。
用户空间
|
V
系统调用 (read, write)
|
V
虚拟文件系统 (VFS)
|
V
通用块层 (Generic Block Layer)
|
V
调度器 -> 请求队列 (request_queue)
|
V
块设备驱动 (gendisk -> driver)
|
V
硬件控制器 (如 SATA, NVMe, SCSI)
表示一个块设备实例(如 /dev/sda):
struct gendisk {
int major; // 主设备号
const struct block_device_operations *fops;
struct request_queue *queue; // 请求队列
struct hd_geometry *geometry;
void *private_data; // 驱动私有数据
...
};
类似字符设备的 file_operations,定义块设备操作接口:
struct block_device_operations {
int (*open)(struct block_device *bdev, fmode_t mode);
void (*release)(struct gendisk *, fmode_t mode);
int (*ioctl)(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg);
...
};
表示设备的 I/O 请求队列:
struct request_queue {
request_fn_proc *request_fn; // 调度器调用的请求处理函数
struct elevator_queue *elevator;
...
};
register_blkdev(major, "myblockdev");
gd = alloc_disk(1);
gd->major = major;
gd->first_minor = 0;
gd->fops = &my_fops;
gd->queue = request_queue;
request_queue = blk_init_queue(my_request_fn, &my_spinlock);
或者使用更现代的:
queue = blk_alloc_queue(GFP_KERNEL);
blk_queue_make_request(queue, my_make_request_fn);
add_disk(gd);
del_gendisk(gd);
put_disk(gd);
blk_cleanup_queue(queue);
unregister_blkdev(major, "myblockdev");
read()
/write()
;bio
结构;bio
转化为 request
;request_fn()
处理请求;end_request()
。struct request {
sector_t sector;
unsigned int nr_sectors;
struct bio *bio;
...
};
struct bio {
sector_t bi_sector;
struct bio_vec *bi_io_vec;
unsigned int bi_vcnt;
...
};
bio 表示逻辑 I/O,支持 scatter-gather。
read()
→ 页缓存 → submit_bio()
→ 请求队列;write()
→ 页缓存修改页 → 标记脏页 → 后台线程写回。submit_bio(READ, bio);
pdflush
/ flush kernel threads
写回。通过 elevator
结构体插拔式实现。
echo deadline > /sys/block/sda/queue/scheduler
一个块设备可划分多个分区(如 /dev/sda1
, /dev/sda2
):
check_partition()
分析分区表;add_disk()
注册子设备。block_device
结构访问底层设备;将普通文件当作块设备使用:
losetup /dev/loop0 /tmp/image.img
mount /dev/loop0 /mnt
驱动接管 I/O 并将其映射为文件偏移读写。
使用物理内存模拟磁盘:
modprobe brd rd_size=65536
mkfs.ext4 /dev/ram0
测试自定义块设备驱动非常有用。
cat /proc/partitions
:查看注册块设备;lsblk
/ blkid
:列出块设备及分区;dmesg
:查看驱动加载日志;iostat
/ iotop
:I/O 统计;strace
:跟踪 I/O 系统调用;blktrace
/ btt
:详细分析 I/O 调度过程;文件路径 | 作用描述 |
---|---|
block/blk-core.c |
核心块 I/O 处理逻辑 |
block/blk-mq.c |
多队列支持逻辑(现代 NVMe) |
drivers/block/ |
各类块设备驱动(loop, brd 等) |
include/linux/blkdev.h |
gendisk, request_queue 等定义 |
include/linux/bio.h |
bio 结构体定义 |
fs/block_dev.c |
VFS 中的块设备接口实现 |
losetup
测试 loopback 设备行为;blktrace
分析 I/O 处理细节;