introduction to device drivers【LDD3 01】

ldd3: https://lwn.net/Kernel/LDD3/

做Linux下驱动开发有段时间了,但是有时候对Linux kernel涉及到的部分依然不甚明了,所以打算再把kernel相关的一些书籍过一遍,同时分享下自己的理解。既然是做driver,就从ldd3开始吧。今天是第一篇,从导论开始吧,虽然看上去导论很浅显,但是往往能起到提纲挈领的左右,有助于对device driver有个全盘的了解。

Linux kernel虽然复杂和庞大,但是最核心的部分仍然是设备驱动。为什么这么说呢?kernel作为操作系统的底层,直接管理着所有连接的device,用户的几乎任何一个操作,都会对应到物理设备。比如你通过键盘敲击一个字符,就需要中断处理例程,USB设备驱动,再到用户态的字符处理程序,屏幕上显示的内容发生了变化,就需要windows manager等重新绘制,X server使用GPU驱动绘制framebuffer,并最终交给显示驱动,最后显示在显示器中。可以说device driver是kernel非常核心的部分,也是OS最终的操作对象。

对于开发者而言,device driver可难可易,可以简单也可以复杂,取决于设备本身,当然也跟开发者的个人能力有关。ldd3认为device driver实现的基本原则有两个,机制(mechanism)和策略(policy)。这不止是device driver的开发,任何程序的设计都应该以这两个原则为出发点,比如接口的设计和实现,就应该只考虑机制的实现,不应该关注client会怎么样用。我一个接口该实现设么样的功能就只实现什么样的功能,不对client的用法做任何假设,否则只会导致接口实现逻辑混乱,模块耦合,接口不合理等等。device driver更是如此。复杂的设备驱动可能会涉及到内存管理,schedule的实现,设备寄存器的读写访问,用户态程序的功能实现等等,如果写驱动脑袋不清楚,每实现一个接口都要考虑别人会怎么用,那实现出来的设备驱动必然是bug百出,难以维护的。总而言之,policy-free是非常重要的实现原则,虽然能在coding的时候想清楚哪些是machanism,哪些是policy,是很不容易的事。

device driver作为loadable的module driver,天生注定了要依靠kernel的utility来实现各种功能,包括上文提到的内存的管理,调度,乃至设备寄存器的访问。kernel的角色自然非常重要,进程管理,内存管理,文件系统,设备控制,网络数据管理等等,无论哪一部分,都是整个操作系统的基础。驱动的好坏,往往取决于是否对kernel的这些功能熟悉,是否使用得当,驱动开发难就难在这里,需要结合kernel的feature,实现自己的业务逻辑,对kernel不熟,要么浪费时间自己造轮子,要么驱动性能/功能差。所以即便是写device driver,如果能对整个kernel有个全盘了解,也会有很大帮助,有助于实现功能全面,性能优越,可扩展,可维护性好的驱动程序。

kernel里有很多优秀的设计,比如module,每个驱动程序的实现都是一个个独立的module driver,可以在runtime动态的加载和卸载。说白了就是动态链接库,kernel就是manager,module driver就是一个个的小弟,需要什么资源就向老大申请,老大按需分配。所有的driver按照type或者class分好组,方便组织和管理,driver只需要按照kernel的要求实现固定的一些callback,就能正常工作,极大的减少了driver developer的工作难度,同时又赋予driver足够的灵活性,可以不受拘束的实现自己业务上的逻辑。一个优秀的操作系统就是如此,你想要的都给你,又给你充分的自由,像极了爱情。

kernel的组成部分,核心就这么多,但是每一个部分展开都是一个巨大的工程。subsystem向下封装device driver,向上提供接口,kernel里的每一层都各司其职,软件工程里万年不变的准则,只要中间加一层,就可以解决一切问题,看似各个功能松散,实际保证了各个功能的独立性,互不干扰。

绝大部分设备都属于字符设备,即character device,还有一类是block device,以及network device。这几种设备对于数据的处理是不一样的,字符设备是按照字节流的方式来处理,block device是按照data block处理,network device则是按照packet来处理。驱动开发者需要知道自己的设备是属于什么设备,因为driver的用法会不一样,字符设备在注册的时候,需要调用字符设备特定的接口,block 设备和网络设备也是调用对应的接口。因为设备的属性不同,kernel对这些设备的处理也是不透明的,需要driver开发者自己处理。

模块化可以说是所有软件工程里的设计准则,各个模块功能独立,如果按照cs模型看,每个模块既是client也是server。

作为introduce,没有涉及到coding的部分,主要是对kernel进行high level的description,认清kernel和device driver的角色和职责,为后面sample driver的coding做好准备。

ldd3 overview:

chapter 2 introducing modularization

chapter 3 sample driver that based on memory, instead of actual hardware device, "device" can be read/written via sample driver.

chapter 4 debug technology.

chapter 5 concurrency and race condition.

chapter 6 advance topic, blocking operation of char device, use of select and ioctl.

chapter 7 time manage in kernel

chapter 8 memory allocation.

chapter 9 management of device I/O and device memory.

chapter 10 interrupt handle.

chapter 11 use kernel structure and portable code.

chapter 12 pci device driver.

chapter 13 USB device.

chapter 14 kernel bottom-up device model infrastructure.

chapter 15 kernel memory management.

chapter 16 block device driver.

chapter 17 network device driver.

发布了32 篇原创文章 · 获赞 6 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/scutth/article/details/105083721
今日推荐