linux设备驱动模型架构分析 一

概述

LDD3中说:“Linux内核需要一个对系统结构的一般性描述。”这个描述就是linux设备驱动模型(下面简称为LDDM)。LDDM不是独立存在,其体系如下图所示:

对架构的每一部分本文都会开辟独立的章节进行描述。暂且抛开这个架构,首先从总体上了解一下LDDM。

LDDM与驱动程序密切相关,而驱动程序处于linux系统中的什么位置呢?我们自顶向下一步步来说,先看下图[以下内容以http://www.wowotech.net/sort/device_model中的内容为主体结合自己的认识和对于4.1内核的修改,这个系列文章非常好,推荐],linux由五个部分组成



1. Process Scheduler,也称作进程管理、进程调度。负责管理CPU资源,以便让各个进程可以以尽量公平的方式访问CPU

2. Memory Manager,内存管理。负责管理Memory(内存)资源,以便让各个进程可以安全地共享机器的内存资源。另外,内存管理会提供虚拟内存的机制,该机制可以让进程使用多于系统可用Memory的内存,不用的内存会通过文件系统保存在外部非易失存储器中,需要使用的时候,再取回到内存中。

3. VFSVirtual File System),虚拟文件系统。Linux内核将不同功能的外部设备,例如Disk设备(硬盘、磁盘、NAND FlashNor Flash等)、输入输出设备、显示设备等等,抽象为可以通过统一的文件操作接口(openclosereadwrite等)来访问。这就是Linux系统“一切皆是文件”的体现(其实Linux做的并不彻底,因为CPU、内存、网络等还不是文件,如果真的需要一切皆是文件)。

4. Network,网络子系统。负责管理系统的网络设备,并实现多种多样的网络标准。

5. IPCInter-Process Communication),进程间通信。IPC不管理任何的硬件,它主要负责Linux系统中进程之间的通信。

其中与设备驱动相关的是VFS子系统,VFS子系统包含5个模块:

1. Device Drivers,设备驱动,用于控制所有的外部设备及控制器。由于存在大量不能相互兼容的硬件设备(特别是嵌入式产品),所以也有非常多的设备驱动。因此,Linux内核中将近一半的Source Code都是设备驱动,大多数的Linux底层工程师(特别是国内的企业)都是在编写或者维护设备驱动,而无暇估计其它内容(它们恰恰是Linux内核的精髓所在)。

2. Device Independent Interface, 该模块定义了描述硬件设备的统一方式(统一设备模型),所有的设备驱动都遵守这个定义,可以降低开发的难度。同时可以用一致的形势向上提供接口。这一层体现了linux设备驱动模型的核心思想。

3. Logical Systems,每一种文件系统,都会对应一个Logical System(逻辑文件系统),它会实现具体的文件系统逻辑。使用mount命令可以看到。

4. System Independent Interface,该模块负责以统一的接口(块设备和字符设备)表示硬件设备和逻辑文件系统,这样上层软件就不再关心具体的硬件形态了。

5. System Call Interface,系统调用接口,向用户空间提供访问文件系统和硬件设备的统一的接口。

从图中可以看出,VFS包含了设备驱动的大部分内容(网络驱动不属于“文件”),设备无关接口体现的就是linux设备驱动模型的核心思想。

LDDM核心思想

如前所述,由于Linux支持世界上几乎所有的、不同功能的硬件设备(这是Linux的优点),导致Linux内核中有一半的代码是设备驱动,而且随着硬件的快速升级换代,设备驱动的代码量也在快速增长。为了降低设备多样性带来的Linux驱动开发的复杂度,以及设备热拔插处理、电源管理等,Linux内核提出了设备模型(也称作Driver Model)的概念。设备模型将硬件设备归纳、分类,然后抽象出一套标准的数据结构和接口。驱动的开发,就简化为对内核所规定的数据结构的填充和实现

因此,Linux设备驱动模型是一种抽象,为内核建立起统一的设备模型。其目的是:

提供一个对系统结构的一般性抽象描述。

LDDM跟踪所有系统所知道的设备,以便让LDDM核心程序协调驱动与新设备之间的关系。

内核使用Linux设备驱动模型支持如下任务:

1. 电源管理和系统关机

2. 与用户空间通信

   sys虚拟文件系统的实现与设备模型密切相关,并且向外界展示了它所表述的结构。向用户空间所提供的系统信息,以及改变操作参数的接口,都要通过/sys文件系统实现,即通过设备模型实现。

3. 热插拔设备

   处理与用户空间进行热插拔设备的通信是通过设备模型管理的。

4. 设备类型

   设备模型包括了对设备分类的机制,它会在更高的功能层上描述这些设备,并使得这些设备对用户空间可见。尤其是将命名设备的功能从内核层转移到用户层,大大提高了设备管理的灵活性。

5. 对象生命周期管理

   设备模型实现一系列机制以处理对象的生命周期、对象之间的关系,以及这些对象在用户空间中的表示。简化编程人员创建和管理对象的工作。

Linux设备驱动模型使用一系列抽象(面向对象设计里的类),提供统一的设备管理视图,这些抽象包括:总线、类、设备和设备驱动。

Bus(总线):总线是CPU和一个或多个设备之间信息交互的通道。而为了方便设备模型的抽象,所有的设备都应连接到总线上无论是CPU内部总线、虚拟的总线还是“platform Bus在计算机中有这样一类设备,它们通过各自的设备控制器,直接和CPU连接,CPU可以通过常规的寻址操作访问它们(或者说访问它们的控制器)。这种连接方式,并不属于传统意义上的总线连接。但设备模型应该具备普适性,因此Linux就虚构了一条Platform Bus,供这些设备挂靠。

Class(分类):在Linux设备模型中,Class的概念非常类似面向对象程序设计中的Class(类),它主要是集合具有相似功能或属性的设备,这样就可以抽象出一套可以在多个设备之间共用的数据结构和接口函数。因而从属于相同Class的设备的驱动程序,就不再需要重复定义这些公共资源,直接从Class中继承即可。

Device(设备):抽象系统中所有的硬件设备,描述它的名字、属性、从属的Bus、从属的Class等信息。

另外,linux驱动模型还有一类抽象,Device Driver(设备驱动)Linux设备模型用Driver抽象硬件设备的驱动程序,它包含设备初始化、电源管理相关的接口实现。而Linux内核中的驱动开发,基本都围绕该抽象进行(实现所规定的接口函数)。

上面提到过,Linux内核通过sys文件系统展示了设备驱动模型的内在结构,我们通过sys文件系统来看看上述抽象如何组织在一起,如何有序的管理linux设备:

可以看到,linux驱动模型是个复杂的体系,包括设备树、总线树、类树,即使一个简单的系统设备模型也会包含几百个节点,但是Linux设备驱动模型代码会处理好这些关系,模型隐藏在交互背后。

综上所述,Linux设备驱动模型的核心思想是

 1. Devicestruct device)和Device Driverstruct device_driver)两个数据结构,分别从“有什么用”“怎么用”两个角度描述硬件设备。这样就统一了编写设备驱动的格式,使驱动开发从论述题变为填空体,从而简化了设备驱动的开发。

2. 同样使用DeviceDevice Driver两个数据结构,实现硬件设备的即插即用(热拔插)。

Linux内核中,只要任何DeviceDevice Driver具有相同的名字,内核就会执行Device Driver结构中的初始化函数(probe),该函数会初始化设备,使其为可用状态。

而对大多数热拔插设备而言,它们的Device Driver一直存在内核中。当设备没有插入时,其Device结构不存在,因而其Driver也就不执行初始化操作。当设备插入时,内核会创建一个Device结构(名称和Driver相同),此时就会触发Driver的执行。这就是即插即用的概念。

3. 通过"Bus-->Device”类型的树状结构解决设备之间的依赖,而这种依赖在开关机、电源管理等过程中尤为重要。

试想,一个设备挂载在一条总线上,要启动这个设备,必须先启动它所挂载的总线。很显然,如果系统中设备非常多、依赖关系非常复杂的时候,无论是内核还是驱动的开发人员,都无力维护这种关系。

而设备模型中的这种树状结构,可以自动处理这种依赖关系。启动某一个设备前,内核会检查该设备是否依赖其它设备或者总线,如果依赖,则检查所依赖的对象是否已经启动,如果没有,则会先启动它们,直到启动该设备的条件具备为止。而驱动开发人员需要做的,就是在编写设备驱动时,告知内核该设备的依赖关系即可。

4. 使用Class结构,在设备模型中引入面向对象的概念,这样可以最大限度地抽象共性,减少驱动开发过程中的重复劳动,降低工作量。


展开阅读全文

没有更多推荐了,返回首页