一 块设备程序的引入
1.1 字符设备程序总结
不妨先总结下字符设备驱动程序,内核引入字符设备来操作硬件设备,大致的框架如下:
app: open read write
--------------------
drv: open read write
--------------------
hardware
应用程序通过 c 库提供的系统调用接口调用 open、read、write 等,将会直接的调用的驱动的 open、read、write 函数。在驱动中的 open、read、write 将会操作实际的硬件设备。
那驱动中的 open、read、write 函数和系统调用提供的 open、read、write 函数怎么对应起来呢?
- 申请主设备号
- 实现 open、read、write 函数
- 将实现的 open、read、write 函数绑定到 fops 结构中
- 注册字符设备,将主设备号和 fops 绑定起来,并告诉内核
因此,APP 在 open 对应设备的时候,就可以通过主设备号找到该设备,接着找到对应的 fops 结构,调用驱动中对应的接口函数。
1.2 按键字符设备驱动总结
按键驱动的实现方式多种多样,以一个简单的场景最为例子:
在一个屋子里,有一个小孩在睡觉,他的妈妈在外面干活,现在妈妈要知道孩子什么时候醒来,妈妈需要怎么做?
查询方式
每隔两分钟,进屋里看一次,看看孩子醒了没。休眠唤醒
妈妈进屋,发现孩子没醒,也在旁边睡下,等孩子醒了,会叫醒她。Poll机制
休眠唤醒存在一个问题,倘若孩子生病了,一睡不醒,那孩子就不会唤醒妈妈,妈妈也将会一直睡眠。为了规避这种情况,加一个30分钟响一次的闹钟,除了孩子醒了主动唤醒妈妈的手段外,妈妈每隔30分钟也会被闹钟唤醒一次。异步通知
妈妈不需要关注小孩醒了没,小孩醒了会自己起来,出屋子去找妈妈。输入子系统
上述驱动都有一个缺点,上述方式写的代码都只有自己团队成员知道怎么用,并不通用。使用内核提供的统一的子系统实现,可以提高代码的通用性。输入子系统仅仅是针对按键驱动,如果是其他设备可能是使用其他内核子系统封装。如 lcd 使用 Frame Buffer。