怎么读到这本书的
去年做了一个ZNS SSD的项目,但是主要验证测试都是基于dnvme驱动的。考虑到跟客户的环境可能有偏差,另外dnvme不适合拿来测试存储软件栈,需要在nvme驱动里面实现这个指令集。我作为多年纸上谈兵的linux爱好者,主动抗了这个任务。临阵磨刀找书看:《Linux Device Drivers》虽然经典,但是已经很久没有更新了。有人推荐了这本书,索性就看呗。
感想
看到作者的前言中对本书的定位时,有点想换书了:这本书不是手把手教你写驱动的,而是教给你驱动为什么要写成那个样子,内核提供的各种机制应该怎样取舍。这就像是在policy vs mechanism中,本书重点放在了解释mechanism。转念一想,把机制弄懂了,也不枉磨刀不误砍柴工了。索性就把书看完了。
印象最深的是,本书开篇便用的大篇幅讲module是怎么被加载进内核的:ko文件的结构是什么,内核怎么读这个文件,各个分段都加载到什么地方,符号表是怎么解析的,导出的符号是怎么在内核中处理的,如此等等。对比下大多数驱动的书中对加载module的描述,仅仅是说“modprobe比insmod好用,因为它会帮你解决依赖”。本书“不知道要高到哪里去了”。
可能有人要问了,你读了这大几百页书,不还是modprobe吗?没错。但是,假设某一天你需要写一个比modprobe还好用的工具,这几百页书不就没白读吗?万一真有这一天呢o( ̄︶ ̄)o
说点失望的地方:这本书对block层的讲解里面,虽然覆盖了大量的代码,然而对核心架构的描述有些模糊。当然有可能是我的重点关注在block层上,而本书篇幅所限吧。
备忘
- GCC别名:
__attribute__((alias(#fn_name)))
- 用nm查看模块的符号表
- struct file中的private_data用来保存和传递驱动自定义的数据。比如在nvme里面可以存namespace结构。
- RCU
- 读者加锁,在临界区中引用数据
- 写者用自己的新数据去覆盖老数据。但是需要等到老数据没有reference后,所以这里要设置一个callback。
- irq_thread机制:将中断处理工作放到一个kthread中来做。
- kobject_uevent: 这个函数实现了将内核中发生的事件通知到用户空间。
- __must_check: 这个qualifier很有用啊,强制caller来检查返回值。
- vm_area_struct: 这个结构代表了一段连续的虚拟内存空间,相当于
《The Design of the UNIX Operating System》
中的region。 - SetPageReserved: 用这个函数来把物理页面pin住。
- 访问硬件的地址时,可以用读写屏障来保证顺序。
- GDB:
- finish命令:跑完当前函数,并打印退栈信息。
- @操作符:可用于查看内存
addr@len
-
WARN_ON()
: 不触发panic,只是打印栈信息。