没有合适的资源?快使用搜索试试~ 我知道了~
首页linux块设备驱动(linux)
linux块设备驱动(linux)
需积分: 10 27 下载量 165 浏览量
更新于2023-03-03
收藏 650KB PDF 举报
linux块设备驱动(linux) linux块设备驱动(linux) linux块设备驱动(linux) linux块设备驱动(linux)
资源详情
资源推荐
第 1 章
章章
+---------------------------------------------------+
| 写一个块设备驱动 |
+---------------------------------------------------+
| 作者:赵磊 |
| 网名:OstrichFly、飞翔的鸵鸟 |
| email: zhaoleidd@hotmail.com |
+---------------------------------------------------+
| 文章版权归原作者所有。 |
| 大家可以自由转载这篇文章,但原版权信息必须保留。 |
| 如需用于商业用途,请务必与原作者联系,若因未取得 |
| 授权而收起的版权争议,由侵权者自行负责。 |
+---------------------------------------------------+
同样是读书,读小说可以行云流水,读完后心情舒畅,意犹未尽;读电脑书却举步艰难,读完后目光呆
滞,也是意犹未尽,只不过未尽的是痛苦的回忆。
滞
研究证明,痛苦的记忆比快乐的更难忘记,因此电脑书中的内容比小说记得持久。
研
而这套教程的目的是要打破这种状况,以至于读者在忘记小说内容忘记本文。
而而
在这套教程中,我们通过写一个建立在内存中的块设备驱动,来学习 linux 内核和相关设备驱动知识。
内
选择写块设备驱动的原因是:
选
1:容易上手
:
2:可以牵连出更多的内核知识
:
3:像本文这样的块设备驱动教程不多,所以需要一个
好吧,扯淡到此结束,我们开始写了。
本章的目的用尽可能最简单的方法写出一个能用的块设备驱动。
所谓的能用,是指我们可以对这个驱动生成的块设备进行 mkfs,mount 和读写文件。
和
为了尽可能简单,这个驱动的规模不是 1000 行,也不是 500 行,而是 100 行以内。
行行
这里插一句,我们不打算在这里介绍如何写模块,理由是介绍的文章已经满天飞舞了。
这
如果你能看得懂、并且成功地编译、运行了这段代码,我们认为你已经达到了本教程的入学资格,
如
当然,如果你不幸的卡在这段代码中,那么请等到搞定它以后再往下看:
当
mod.c:
#include <linux/module.h>
static int __init init_base(void)
{
printk("----Hello. World----");
return 0;
}
}
static void __exit exit_base(void)
{
printk("----Bye----\n");
}
}
module_init(init_base);
module_exit(exit_base);
m
MODULE_LICENSE ("GPL");
MODULE_AUTHOR("Zhao Lei");
MODULE_DESCRIPTION("For test");
M
Makefile:
obj-m := mod.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
P
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
clean:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) clean
rm -rf Module.markers modules.order Module.symvers
rr
好了,这里我们假定你已经搞定上面的最简单的模块了,懂得什么是看模块,以及简单模块的编写、编
译、加载和卸载。
译
还有就是,什么是块设备,什么是块设备驱动,这个也请自行 google 吧,因为我们已经迫不及待要写完
程序下课。
程程
为了建立一个可用的块设备,我们需要做......1 件事情:
件
1:用 add_disk()函数向系统中添加这个块设备
函
添加一个全局的
static struct gendisk *simp_blkdev_disk;
然后申明模块的入口和出口:
module_init(simp_blkdev_init);
module_exit(simp_blkdev_exit);
然后在入口处添加这个设备、出口处私房这个设备:
static int __init simp_blkdev_init(void)
{
add_disk(simp_blkdev_disk);
return 0;
}
static void __exit simp_blkdev_exit(void)
{
del_gendisk(simp_blkdev_disk);
}
}
当然,在添加设备之前我们需要申请这个设备的资源,这用到了 alloc_disk()函数,因此模块入口函
数 simp_blkdev_init(void)应该是:
应
static int __init simp_blkdev_init(void)
{
simp_blkdev_disk = alloc_disk(1);
if (!simp_blkdev_disk) {
ret = -ENOMEM;
goto err_alloc_disk;
}
}
add_disk(simp_blkdev_disk);
a
return 0;
r
err_alloc_disk:
return ret;
}
还有别忘了在卸载模块的代码中也加一个行清理函数:
还
put_disk(simp_blkdev_disk);
p
还有就是,设备有关的属性也是需要设置的,因此在 alloc_disk()和 add_disk()之间我们需要:
之
strcpy(simp_blkdev_disk->disk_name, SIMP_BLKDEV_DISKNAME);
simp_blkdev_disk->major = ?1;
simp_blkdev_disk->first_minor = 0;
simp_blkdev_disk->fops = ?2;
simp_blkdev_disk->queue = ?3;
set_capacity(simp_blkdev_disk, ?4);
s
SIMP_BLKDEV_DISKNAME 其实是这个块设备的名称,为了绅士一些,我们把它定义成宏了:
其
#define SIMP_BLKDEV_DISKNAME "simp_blkdev"
#
这里又引出了 4 个问号。(天哪,是不是有种受骗的感觉,像是陪老婆去做头发)
第 1 个问号:
个
每个设备需要对应的主、从驱动号。
我们的设备当然也需要,但很明显我不是脑科医生,因此跟写 linux 的那帮疯子不熟,得不到预先为我
保留的设备号。
保
还有一种方法是使用动态分配的设备号,但在这一章中我们希望尽可能做得简单,因此也不采用这种方
法。
法
那么我们采用的是:抢别人的设备号。
我们手头没有 AK47,因此不敢干的太轰轰烈烈,而偷偷摸摸的事情倒是可以考虑的。
,
柿子要捡软的捏,而我们试图找出一个不怎么用得上的设备,然后抢他的 ID。
。
打开 linux/include/linux/major.h,把所有的设备一个个看下来,我们觉得最胜任被抢设备号的
家伙非 COMPAQ_SMART2_XXX 莫属。
莫
第一因为它不强势,基本不会被用到,因此也不会造成冲突;第二因为它有钱,从
COMPAQ_SMART2_MAJOR 到 COMPAQ_SMART2_MAJOR7 有那 8 个之多的设备号可以被抢,不过瘾的话还
有它妹妹:COMPAQ_CISS_MAJOR~COMPAQ_CISS_MAJOR7。
。
为了让抢劫显得绅士一些,我们在外面又定义一个宏:
#define SIMP_BLKDEV_DEVICEMAJOR COMPAQ_SMART2_MAJOR
然后在?1 的位置填上 SIMP_BLKDEV_DEVICEMAJOR。
。
第 2 个问号:
个
gendisk 结构需要设置 fops 指针,虽然我们用不到,但该设还是要设的。
指
好吧,就设个空得给它:
在全局部分添加:
struct block_device_operations simp_blkdev_fops = {
.owner = THIS_MODULE,
};
然后把?2 的位置填上&simp_blkdev_fops。
。
第 3 个问号:
个
这个比较麻烦一些。
首先介绍请求队列的概念。对大多数块设备来说,系统会把对块设备的访问需求用 bio 和 bio_vec 表
示,然后提交给通用块层。
示
通用块层为了减少块设备在寻道时损失的时间,使用 I/O 调度器对这些访问需求进行排序,以尽可能提
高块设备效率。
高
关于 I/O 调度器在本章中不打算进行深入的讲解,但我们必须知道的是:
1:I/O 调度器把排序后的访问需求通过 request_queue 结构传递给块设备驱动程序处理
结
2:我们的驱动程序需要设置一个 request_queue 结构
结
申请 request_queue 结构的函数是 blk_init_queue(),而调用 blk_init_queue()函数时需要传
入一个函数的地址,这个函数担负着处理对块设备数据的请求。
因此我们需要做的就是:
1:实现一个 static void simp_blkdev_do_request(struct request_queue *q)函数。
函
2:加入一个全局变量,指向块设备需要的请求队列:
static struct request_queue *simp_blkdev_queue;
3:在加载模块时用 simp_blkdev_do_request()函数的地址作参数调用 blk_init_queue()初始化
一个请求队列:
一
simp_blkdev_queue = blk_init_queue(simp_blkdev_do_request, NULL);
if (!simp_blkdev_queue) {
ret = -ENOMEM;
goto err_init_queue;
}
4:卸载模块时把 simp_blkdev_queue 还回去:
还
blk_cleanup_queue(simp_blkdev_queue);
5:在?3 的位置填上 simp_blkdev_queue。
。
第 4 个问号:
个
这个还好,比前面的简单多了,这里需要设置块设备的大小。
块设备的大小使用扇区作为单位设置,而扇区的大小默认是 512 字节。
字
当然,在把字节为单位的大小转换为以扇区为单位时,我们需要除以 512,或者右移 9 位可能更快一些。
。
同样,我们试图把这一步也做得绅士一些,因此使用宏定义了块设备的大小,目前我们定为 16M:
:
#define SIMP_BLKDEV_BYTES (16*1024*1024)
然后在?4 的位置填上 SIMP_BLKDEV_BYTES>>9。
。。
看到这里,是不是有种身陷茫茫大海的无助感?并且一波未平,一波又起,在搞定这 4 个问号的同时,
居然又引入了 simp_blkdev_do_request 函数!
函
当然,如果在身陷茫茫波涛中时你认为到处都是海,因此绝望,那么恭喜你可以不必挨到 65 岁再退休;
岁
反之,如果你认为到处都是没有三聚氰胺鲜鱼,并且随便哪个方向都是岸时,那么也恭喜你,你可以活
着回来继续享受身为纳税人的荣誉。
着着
为了理清思路,我们把目前为止涉及到的代码整理出来:
为
#define SIMP_BLKDEV_DEVICEMAJOR COMPAQ_SMART2_MAJOR
#define SIMP_BLKDEV_DISKNAME "simp_blkdev"
#define SIMP_BLKDEV_BYTES (16*1024*1024)
#
static struct request_queue *simp_blkdev_queue;
static struct gendisk *simp_blkdev_disk;
s
static void simp_blkdev_do_request(struct request_queue *q);
s
struct block_device_operations simp_blkdev_fops = {
.owner = THIS_MODULE,
};
}
static int __init simp_blkdev_init(void)
{
int ret;
i
simp_blkdev_queue = blk_init_queue(simp_blkdev_do_request, NULL);
if (!simp_blkdev_queue) {
ret = -ENOMEM;
剩余119页未读,继续阅读
tjx163
- 粉丝: 18
- 资源: 392
上传资源 快速赚钱
- 我的内容管理 收起
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
会员权益专享
最新资源
- 电容式触摸按键设计参考
- 西门子MES-系统规划建议书(共83页).docx
- 6、毕设参考资料 for.pdf
- hive基础查询文档上传
- RouterOS PPPOE 多拨负载均衡PCC.pdf
- 微机系统实验一学习笔记(个人监督)
- 基于SpringBoot的企业客户管理系统源码数据库.docx
- 基于springboot的IT技术交流和分享平台源码数据库.docx
- 基于springboot的图书馆管理系统源码数据库.docx
- 基于SpringBoot的在线拍卖系统源码数据库.docx
- 基于springboot的网上点餐系统源码数据库.docx
- 基于SpringBoot的网上订餐系统源码数据库.docx
- 基于SpringBoot的在线视频教育平台源码数据库.docx
- 基于springboot的中小型医院网站源码数据库.docx
- 基于springboot的中药实验管理系统源码数据库.doc
- 基于springboot的校园周边美食探索及分享平台源码数据库.docx
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功