Linux如何编写块设备驱动_LinuxBlockDriver开发教程

发布时间 - 2025-11-25 00:00:00    点击率:
首先实现块设备驱动需理解gendisk与request_queue的作用,1. gendisk描述设备信息并注册到系统;2. request_queue管理I/O请求并通过make_request处理bio;3. 每个bio包含多个段,驱动需遍历并完成数据拷贝;4. 模块卸载时按顺序释放资源;5. 编译后通过insmod加载并用mkfs、mount测试。

编写Linux块设备驱动需要理解内核中块I/O子系统的基本架构和数据流。块设备与字符设备不同,它以固定大小的数据块为单位进行读写,并支持随机访问。典型的块设备包括硬盘、SSD、U盘等。本文将带你一步步实现一个简单的内存模拟块设备驱动(RAM Disk),帮助你掌握Linux块设备驱动开发的核心要点。

1. 理解块设备驱动的基本结构

Linux块设备驱动主要依赖于struct gendiskstruct request_queue两个核心结构体:

  • gendisk:描述一个逻辑块设备,包含设备名、主次设备号、分区信息等。
  • request_queue:管理来自文件系统的I/O请求,驱动需为其注册请求处理函数。

块设备不直接处理read/write系统调用,而是通过请求队列接收bio(block I/O)结构,由驱动完成数据搬运。

2. 创建请求队列与gendisk实例

在模块初始化函数中,需分配并初始化请求队列和gendisk:

static struct request_queue *queue;
static struct gendisk *disk;

static int __init my_blk_init(void) { // 分配请求队列 queue = blk_alloc_queue(GFP_KERNEL); if (!queue) return -ENOMEM;

// 设置请求处理函数
blk_queue_make_request(queue, my_make_request);

// 分配gendisk结构(1个分区)
disk = alloc_disk(1);
if (!disk) {
    blk_cleanup_queue(queue);
    return -ENOMEM;
}

disk->major = MY_BLK_MAJOR;         // 主设备号
disk->first_minor = 0;
disk->fops = &my_blk_fops;          // 文件操作(通常为空或仅占位)
disk->queue = queue;
strcpy(disk->disk_name, "myblk");

// 设置容量(以512字节扇区为单位)
set_capacity(disk, MY_BLK_SIZE / 512);

// 注册设备
add_disk(disk);

return 0;

}

3. 实现make_request函数处理I/O

传统方式使用make_request函数逐个处理bio。每个bio代表一次I/O操作,可能包含多个段(segment):

static int my_make_request(struct request_queue *q, struct bio *bio)
{
    struct bio_vec bvec;
    sector_t sector = bio->bi_iter.bi_sector;
    void *mem = myblk_data + (sector * 512); // 内存偏移
    bool is_write = op_is_write(bio_op(&bio));
if (sector * 512 + bio->bi_iter.bi_size > MY_BLK_SIZE) {
    bio_endio(bio, -EIO);
    return 0;
}

bio_for_each_segment(bvec, bio, iter) {
    char *bdata = kmap_atomic(bvec.bv_page) + bvec.bv_offset;
    if (is_write)
        memcpy(mem, bdata, bvec.bv_len);
    else
        memcpy(bdata, mem, bvec.bv_len);
    kunmap_atomic(bdata - bvec.bv_offset);
    mem += bvec.bv_len;
}

bio_endio(bio, 0);
return 0;

}

注意:现代内核推荐使用blk_mq_make_request配合多队列机制,但简单驱动仍可用传统方式。

4. 清理资源与模块卸载

模块卸载时必须释放申请的资源,顺序不能错:

static void __exit my_blk_exit(void)
{
    del_gendisk(disk);
    put_disk(disk);
    blk_cleanup_queue(queue);
}

确保在del_gendisk后不再有新的I/O进入,避免空指针访问。

5. 编译与测试

编写Makefile:

obj-m += myblk.o

KDIR := /lib/modules/$(shell uname -r)/build

all: $(MAKE) -C $(KDIR) M=$(PWD) modules

clean: $(MAKE) -C $(KDIR) M=$(PWD) clean

编译后加载模块:

sudo insmod myblk.ko
dmesg | tail        # 查看设备号
lsblk               # 应看到 myblk 设备
sudo mkfs.ext4 /dev/myblk
sudo mount /dev/myblk /mnt
echo "hello" > /mnt/test.txt

基本上就这些。从零写块设备驱动的关键是理解bio的处理流程和内存映射方式。虽然真实硬件驱动还需处理DMA、中断等,但内存模拟设备是学习的良好起点。调试时多用dmesg观察内核输出,逐步验证读写正确性。


# linux  # 字节  # u盘  # 硬盘  # ai  # 架构  # 结构体  # 指针  # Struct  # 空指针  # 多个  # 加载  # 遍历  # 推荐使用  # 为其  # 带你  # 还需  # 文件系统  # 它以  # 为空 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 如何用西部建站助手快速创建专业网站?  如何快速重置建站主机并恢复默认配置?  Linux后台任务运行方法_nohup与&使用技巧【技巧】  javascript中对象的定义、使用以及对象和原型链操作小结  在centOS 7安装mysql 5.7的详细教程  米侠浏览器网页背景异常怎么办 米侠显示修复  VIVO手机上del键无效OnKeyListener不响应的原因及解决方法  laravel怎么实现图片的压缩和裁剪_laravel图片压缩与裁剪方法  Laravel如何实现文件上传和存储?(本地与S3配置)  php485函数参数是什么意思_php485各参数详细说明【介绍】  Laravel Seeder填充数据教程_Laravel模型工厂Factory使用  网站图片在线制作软件,怎么在图片上做链接?  Laravel如何实现模型的全局作用域?(Global Scope示例)  Laravel如何配置和使用队列处理异步任务_Laravel队列驱动与任务分发实例  个人网站制作流程图片大全,个人网站如何注销?  如何在浏览器中启用Flash_2025年继续使用Flash Player的方法【过时】  简历没回改:利用AI润色让你的文字更专业  如何在景安服务器上快速搭建个人网站?  Firefox Developer Edition开发者版本入口  laravel怎么在请求结束后执行任务(Terminable Middleware)_laravel Terminable Middleware请求结束任务执行方法  高端建站三要素:定制模板、企业官网与响应式设计优化  如何在自有机房高效搭建专业网站?  厦门模型网站设计制作公司,厦门航空飞机模型掉色怎么办?  Windows驱动无法加载错误解决方法_驱动签名验证失败处理步骤  Laravel如何使用Seeder填充数据_Laravel模型工厂Factory批量生成测试数据【方法】  如何挑选高效建站主机与优质域名?  如何用AI一键生成爆款短视频文案?小红书AI文案写作指令【教程】  Laravel用户认证怎么做_Laravel Breeze脚手架快速实现登录注册功能  香港服务器租用每月最低只需15元?  标准网站视频模板制作软件,现在有哪个网站的视频编辑素材最齐全的,背景音乐、音效等?  Python函数文档自动校验_规范解析【教程】  Laravel如何安装Breeze扩展包_Laravel用户注册登录功能快速实现【流程】  做企业网站制作流程,企业网站制作基本流程有哪些?  清除minerd进程的简单方法  SQL查询语句优化的实用方法总结  如何在IIS中配置站点IP、端口及主机头?  Laravel请求验证怎么写_Laravel Validator自定义表单验证规则教程  googleplay官方入口在哪里_Google Play官方商店快速入口指南  Win10如何卸载预装Edge扩展_Win10卸载Edge扩展教程【方法】  成都品牌网站制作公司,成都营业执照年报网上怎么办理?  悟空浏览器如何设置小说背景色_悟空浏览器背景色设置【方法】  Laravel如何使用API Resources格式化JSON响应_Laravel数据资源封装与格式化输出  Laravel如何实现API版本控制_Laravel版本化API设计方案  如何使用 Go 正则表达式精准提取括号内首个纯字母标识符(忽略数字与嵌套)  网站优化排名时,需要考虑哪些问题呢?  Laravel的辅助函数有哪些_Laravel常用Helpers函数提高开发效率  Laravel怎么使用Blade模板引擎_Laravel模板继承与Component组件复用【手册】  如何在Ubuntu系统下快速搭建WordPress个人网站?  如何用PHP快速搭建CMS系统?  百度浏览器ai对话怎么关 百度浏览器ai聊天窗口隐藏