面向对象地分析Linux内核设备驱动(1):——Linux内核驱动中面向对象的基本规则和实现方法

Linux内核驱动中面向对象的基本规则和实现方法


-         内核版本 Linux Kernel 2.6.34, 与 Robert.Love的《Linux Kernel Development》(第三版)所讲述的内核版本一样

-         源代码下载路径: https://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.34.tar.bz2

1. 引言——为什么要把面向对象的概念引入Linux内核


1). 管理大型软件的复杂度

- 众所周知,现代的软件项目变得越来越复杂,Linux内核更是世界上最大最复杂的软件工程。引用自《代码大全》中的观点,面向对象的设计思想是一种管理软件系统复杂性的手段。


- 人的精力有限,一个程序员在同一时间,只专注于软件系统的一小部分,才能最大的发挥工作效率。构建软件就像设计大型建筑,一个时间点上,我们聚焦在建筑结构蓝图设计时,就不要过分地将注意力分散的建筑内的电线布局,第N层的排水管道如何施工这些细节问题上,而是应该聚焦在整体设计上。


- 面向对象思想就是一种在代码编写之上的软件系统结构设计的思想。面向对象的语言用于描述系统框架结构是怎么样的,需要什么模块,模块之间的关系如何,如何遵守开闭准则,方便后期的维护和开发等一些设计意图层次上的问题。


- 面向对象的设计思想不太关心xxx函数实现如何初始化,要注册什么结构,要把xxx寄存器状态设置为0等流程细节的问题。这些应该是属于面向过程设计时的问题。


- 面向过程与面向对象的思想用途不同,没有好坏之分。面向对象思想更倾向于程序之上的顶层设计与程序系统结构设计,然后真正要实现一个函数细节的时候,还是需要面向过程地分析细节如何实现,需要初始化哪些变量,注册哪些结构,设置哪些寄存器等面向过程的问题。


- 面向对象的思想和语言无关,并不是C++或者JAVA 、Python等语言才有的。面向对象思想,是随着软件系统的复杂度越来越高,面对大规模软件系统设计的问题,而提出的一种管理大型软件系统设计的思想。只是在C语言出现时,计算机软硬件系统还在起步阶段,面向对象的思想尚未发展(可能Keep it simple and stupid 原则也是让C语言语法尽量保持简单的原因),因而C语言中缺乏面向对象相关的核心关键词语法的支持。而JAVA、Python等一些1990年代之后问世的语言,受到C++语言影响以及面向对象思想的逐渐流行,在语法层面就提供了面向对象的核心关键词支持,可以说在处理面向对象问题上具有先天优势。


- 虽然C语言不支持很多面向对象的核心关键词,但是随着Linux内核,Ffmpeg,Nginx等大规模以C语言编写的开源软件项目的发展与推广,C语言遇到的软件复杂度增加以及系统设计与系统长期维护的问题,与JAVA、C++编程遇到的复杂度问题是想通的。并且,面向对象思想也是由于开发者们在开发过程中遇到瓶颈才提出来的,这些问题,不管是用C语言编程还是JAVA编程,都会客观存在。因而用C语言模拟JAVA等面向对象的语言,采用面向对象的思想进行系统顶层设计是很有必要的。


- JAVA是一种类似C语言的命令式语言(用于区别Lisp等函数式编程语言),并且是设计良好的纯面向对象的语言。JAVA有不少关键词与C语言相同,并且JAVA标准制定委员会的很多成员也是C/C++标准制定委员会的。因而借鉴JAVA的面向对象思想,分析编写面向对象的C语言程序,是相当有帮助的。JAVA不同于C++, C++现在的定位是多种范式语言,细节太多,在面向对象特性的设计上也不够友好方便。所以我更倾向于借鉴JAVA的编程思想来分析编程面向对象的C语言代码。


- 文章中很多面向对象思想的出处,都来自JAVA。作为Linux和C语言嵌入式系统相关的开发者,可能大部分缺乏JAVA的编程经验。所以希望读者抽空学习一下JAVA,做一些小练习,拓宽编程的知识面,这样更能够领会面向对象设计的精髓,还能提出一些自己的新的看法。我认为,JAVA实际上是在C语言基础上的的一种改进,很多关键词与C相同,但是又弥补了C语言的不少缺陷,并且专注在面向对象的设计上。


- 本文也是希望起到抛砖引玉的作用,如有概念性问题,还请批评指正。

 

2). 良好的沟通需要一套通用的语言规则

- 将面向对象的概念引入基于Linux系统的C语言程序开发是很有必要的。虽然面向对象思想会带来很多新的概念术语(继承,多态等),很多做Linux驱动开发的工程师都是电子工程相关专业出身,这些概念可能刚接触会稍显晦涩,但是习惯性以面向对象思想分析大规模软件系统之后,能够帮你快速得掌握整个系统的结构以及原作者的设计意图,而不会陷入到一个个API的实现细节中,只见树木,不见森林。接手维护一个大型软件项目,首先要知道原作者的意图,即知道原作者为什么要这么编程,才能理清楚软件设计思路,进而修改扩展源代码。


- 面向对象的术语,是一种通用的规则,大家都掌握该规则,然后按照规则上的术语沟通,就能够用简短的语言表述出程序的意图。例如面向对象思想中的术语——继承基类,实现多态函数,如果用面向过程思想描述就是——定义一个XXX结构体,再定义XX和YY函数,用XX和YY函数填充XXX结构体中的A函数指针和B函数指针,再在初始化函数中调用C函数注册这个XXX结构体。不同思想所用术语的繁简程度,高下立判。过长的语言描述,容易带来更多的误解,信息丢失,理解不全等沟通障碍,这时,专用术语的优势就体现出来了。


- 面向对象思想往往和设计模式是分不开的。比如Linux内核中的通知链系统,用设计模式的术语来说,叫观察者模式,有学过该设计模式的读者,立马明白程序大概做了什么。但是如果不了解这一套语言沟通规则,就代码讲代码,可能又是一堆这样的过程描述性语言——定义一个xxx头,定义xx结构体,设置xx结构体的回调函数,回调函数输入参数是什么,返回什么,注册xx结构到xxx头……

 

3). Linux内核源码是训练面向对象思维的实战场

- 单纯地学习面向对象思想或者设计模式,如何不结合实际的代码来分析具体案例,过一段时间可能就会忘记书上讲了什么东西。


- 平时编写小规模程序时候,只需要一个人,不需要面向对象的思想就能完成,因而觉得面向对象这些东西都是书上的理论,实际上又用不着,但是一旦遇到Linux内核源码这种复杂级别的程序,就不知如何下手,容易一脸懵逼。


- Linux内核是世界上最大的软件工程项目之一,经过了20多年的发展和完善,内部子系统结构经过了不断重构(refracting)和反复迭代设计,其代码质量也是越来越高,这其中肯定从面向对象的编程思想中借鉴模仿了很多东西。当然阅读Linux内核源码时,由于历史原因,还是会有很多代码的命名,架构和设计风格不那么完美(例如videobuf的第一版)。所以阅读内核源码的时候,要学会其精华,同时也要抛弃一些不良的设计。


- JAVA Python等面向对象语言有大量的开源框架,让我们从实战中体验面向对象思想和设计模式。C语言的框架类库可能没有JAVA那么丰富,但是Linux内核作为C语言的代表作品,其中的设计思想是很值得用面向对象的语言分析一遍的,尤其是设备驱动相关的代码,有很多层抽象才变成了用户态都喜爱的文件。


- 其实抛开Linux内核中动态运行,维护系统运转的线程,其中大部分驱动代码都是静态存在于内存,等待被调用的。这样看来Linux内核中维持系统运转的进程就像JAVA虚拟机,而内核中等待被调用的代码,就像JDK的框架和类库,需要用户态去调用,也需要内核态驱动开发者利用框架进一步扩展。这样看来JDK与Linux内核设计思想也有就有了很大共通之处,用面向对象思想分析Linux内核设备驱动也就是一种高屋建瓴,了解各个子系统结构框架的通用思想。


- 网络上有一些C语言面向对象思想编程的文章,但是只是零零散散地整理了一些观点,不够系统化,案例也过于简单。所以我希望结合Linux内核这个大型的实际软件系统,更加系统化地在C语言编程中描述和应用面向对象思想。


- 综上所述,作为Linux系统C语言开发者,带着面向对象的思想,从不同的视角来

  • 16
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值