32 | 字符设备(上):如何建立直销模式?
刘超
该思维导图由 AI 生成,仅供参考
上一节,我们讲了输入输出设备的层次模型,还是比较复杂的,块设备尤其复杂。这一节为了让你更清晰地了解设备驱动程序的架构,我们先来讲稍微简单一点的字符设备驱动。
这一节,我找了两个比较简单的字符设备驱动来解析一下。一个是输入字符设备,鼠标。代码在 drivers/input/mouse/logibm.c 这里。
另外一个是输出字符设备,打印机,代码 drivers/char/lp.c 这里。
内核模块
上一节,我们讲过,设备驱动程序是一个内核模块,以 ko 的文件形式存在,可以通过 insmod 加载到内核中。那我们首先来看一下,怎么样才能构建一个内核模块呢?
一个内核模块应该由以下几部分组成。
第一部分,头文件部分。一般的内核模块,都需要 include 下面两个头文件:
如果你去看上面两个驱动程序,都能找到这两个头文件。当然如果需要的话,我们还可以引入更多的头文件。
第二部分,定义一些函数,用于处理内核模块的主要逻辑。例如打开、关闭、读取、写入设备的函数或者响应中断的函数。
例如,logibm.c 里面就定义了 logibm_open。logibm_close 就是处理打开和关闭的,定义了 logibm_interrupt 就是用来响应中断的。再如,lp.c 里面就定义了 lp_read,lp_write 就是处理读写的。
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
本文深入分析了字符设备驱动程序的架构和内核模块的构建,通过两个简单的字符设备驱动程序,即鼠标和打印机的驱动程序,为读者详细介绍了字符设备的打开、写入和ioctl等最常见的操作。文章首先介绍了内核模块的基本组成部分,包括头文件部分、处理内核模块主要逻辑的函数定义、file_operations结构的定义、模块的初始化和退出函数的定义以及lisense的声明。通过具体的代码示例和解释,帮助读者更清晰地了解了设备驱动程序的架构和内核模块的构建过程。在加载字符设备驱动的过程中,注册字符设备是重要的一步,而后通过mknod在/dev下创建设备文件,最终打开设备文件。通过对字符设备的打开过程进行详细解析,读者可以了解设备驱动程序的内部工作原理。此外,文章还介绍了写入字符设备和使用IOCTL控制设备的过程,以及对应的代码实现和解析。这份技术资料对于想要深入了解操作系统内核开发的读者来说具有重要的参考价值。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《趣谈 Linux 操作系统》,新⼈⾸单¥68
《趣谈 Linux 操作系统》,新⼈⾸单¥68
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(14)
- 最新
- 精选
- geraltlaush另外贴上一个字符设备或者块设备都有一个主设备号和次设备号。主设备号和次设备号统称为设备号。主设备号用来表示一个特定的驱动程序。次设备号用来表示使用该驱动程序的各设备。
作者回复: 赞
2019-06-1027 - 有铭问一下老师你的这些图是用啥工具画的?
作者回复: draw.io
2019-06-104 - geraltlaush还有个收获就是程序设计的面向对象的思想,之前开发一个音视频推流服务器,一个音视频类型的操作编码解码都是类中完成,现在看来可以把操作单独设计成一个基类,各种类型的音视频操作都可以继承这个类,代码可以设计的更为优雅
作者回复: 是的
2019-06-103 - ezra.xu除了open,close,read,write等,是不是可以加入些异常捕获,异步操作,多线程的函数……
作者回复: 这就太复杂啦,每一篇文章都找到一本书
2019-06-11 - 西山薄凉课代表不在了,我来当课代表。 ## 字符设备 ### 内核模块 - 驱动程序的内核模块,以 ko 的文件形式存在,可以通过 insmod 加载到内核中 - 一个内核模块应该由以下几部分组成 - 头文件部分:include <linux/module.h> 及 <linux/init.h> - 定义以内科模块处理逻辑的函数,如开、关、读写及响应中断。 - 定义一个 file_operations 接口,使得对上层接口统一 - 定义整个模块的初始化和退出函数 - 调用 module_init 和 module_exit,分别指向上面两个初始化函数和退出函数 - 声明一下 lisense,调用 MODULE_LICENSE ### 打开字符设备 - 打开字符设备 - 注册字符设备:通过 insmod 加载进内核 - 调用 __register_chrdev_region - 注册设备的主次设备号和名称 - 初始化 cdev 结构体,将其 ops 成员指向设备定义的 file_operations - 调用 cdev_add 将设备添加到内核中的 cdev_map,统一管理字符设备 - 创建设备文件:通过 mknod 在 /dev 下面创建一个设备文件 - 找到设备文件所在的文件夹,然后为这个新创建的设备文件创建一个 dentry,用于关联文件和 inode - 创建特殊 inode,用于关联设备(还可关联FIFO文件、socket等) - 打开设备文件:调用 inode 的 open 函数 - 如果 cdev 还没有关联,从 cdev_map 中找到 cdev 并关联 - 找到 cdev 的 file_operations,将其设置给文件描述符 - 调用设备驱动程序的 file_operations 的 open 函数,真正打开设备 ### 写入字符设备 - 写入字符设备 - 调用文件系统标准接口 write,参数为设备的文件描述符 - 由于已经将 file_operations 替换成了设备的,所以会直接调用设备定义的 write(多态) ### IOCTL控制设备 - 发送 IOCTL 信令控制设备 - cmd 组成(32位): - 最低 8 位为 NR,是命令号; - 然后 8 位是 TYPE,是类型; - 然后 14 位是参数的大小; - 最高 2 位是 DIR,是方向,表示写入、读出,还是读写。 - 有对应的宏方便操作 cmd - 调用 do_vfs_ioctl,分支判断 cmd 执行对应操作,分为以下几种 - 默认定义好的 cmd,执行系统默认操作 - 普通文件,调用 file_ioctl - 其他文件调用 vfs_ioctl - vfs_ioctl 内部还是会直接调用设备定义的 cmd 对应的接收函数,里面对不同 cmd 执行不同操作2020-03-01231
- 小鳄鱼虚拟文件系统,统一所有设备操作。而这个设计,看起来只是使用多态,但是实际上这是抽象出来的统一操作层。有这个想法,要实现对各种各样的设备,繁杂的功能而言,并不简单!而抽象本身,就很复杂了,值得继续深入!!!2022-05-191
- 功夫熊猫老师,能不能把源代码传一份2023-05-10归属地:江苏
- 浩仔是程序员驱动程序里面的write方法是怎么操作打印机的?是不是要把数据写到指定io端口中?2022-11-25归属地:广东
- 核桃字符设备驱动程序没有了解过,但是在github上面找到过实现自定义文件系统的hellofs,这个可以核心关键还是自定义的file operations和注册这些,大同小异的2021-05-05
- 耿长学/proc文件系统的原理是实现是基于什么?/proc里面这些文件使用的是内存存放还是磁盘存放的,当命令终止后这些文件又去了哪里,怎么销毁的,谢谢,之前买了网络协议的学了不去网络原理2019-12-11
收起评论