现在的处理器都具有保护系统软件不受应用程序破坏的功能,实现这个功能的方法是在处理器中实现不同的操作级别,不同的级别具有不同的功能,Linux使用处理器的两种级别,应用程序运行在最低级别,即用户空间(或用户态),内核运行在最高级别,即内核空间(或内核态)。
嵌入式系统都是由硬件系统和软件系统组成
任何一个嵌入式系统都是由硬件系统和软件系统组成的。硬件系统和软件系统的协同保证了嵌入式系统的运行。硬件系统是由集成电路和电子元器件构成的,是所有软件得以运行的平台,程序代码的功能最终靠硬件系统上的组合逻辑和时序逻辑电路实现。操作系统是介于应用程序和机器硬件之间的一个系统软件,它掩盖了系统硬件之间的差别,为用户提供了一个统一的应用编程接口。操作系统和应用程序构成了软件系统,应用程序通过应用编程接口使用操作系统提供的服务。而设备驱动程序是操作系统和硬件之间的接口,它为应用程序屏蔽了硬件的细节,使得应用程序只需要调用操作系统的应用编程接口就可以让硬件来完成要求的工作。
内核和驱动程序之间的接口
不同种类、型号和厂家的设备都有自己的特性。要支持某种设备,就必须提供这种设备的控制代码,如果要把所有设备的驱动程序都写在操作系统内核中,就必然会使内核变得过分庞大,这不利于内核的开发和维护。解决这个问题需要两步:第一步把驱动程序从内核中分离;第二步是在内核和驱动程序之间定义一个统一的接口,双方通过这个接口通信。
因此,对Linux内核来说,驱动程序是一个设备的代表。当Linux内核需要与某个设备通信时,内核首先找到该设备的驱动程序,然后通过标准的接口调用驱动程序的相应函数完成与设备的通信。
由于定义了内核和驱动程序之间的接口,因此驱动程序的开发变得相对容易。设备驱动程序就是对内核和驱动程序之间的接口函数的实现。硬件厂商和第三方用户都可以开发自己的驱动程序。设备驱动程序由一些私有数据和一组函数组成,它是Linux内核的一部分,设备通过驱动程序与内核其他部分交互。
驱动程序都有一些共同的特点:
Linux内核中有许多不同的设备驱动程序,而且其数量还在不断增长,所有的驱动程序都有一些共同的特点:
(1)设备驱动程序运行在内核态,是内核的一部分。如果驱动程序发生错误,就会导致很严重的后果,甚至系统崩溃。
(2)实现标准的内核接口,设备驱动程序必须向Linux内核或它所在的系统提供一组函 数来实现这些标准的内核接口函数。
(3)使用标准的内核服务。虽然驱动程序运行在内核态,但是它不能使用所有的内核服 务,可以使用的内核服务也必须定义在一个接口函数中。
(4)可装载、可配置。这样可以减少内核的大小,节约系统的资源。
初始化配置程序、I/O程序和中断服务程序是Linux下的设备驱动程序的三个主要组成部分。初始化配置程序检测硬件存在与否,能不能正常工作,在可以正常工作的前提下初始化硬件。用户空间函数通过I/O程序完成数据的通信。应用程序进行的系统调用是该部分程序完成的。Linux内核负责在用户态与内核态的切换。中断服务程序是硬件产生中断后被内核调用的一段程序代码,因为中断产生时Linux内核有正在运行的进程,所以中断服务程序禁止依赖进程的上下文。
本文节选自《嵌入式Linux驱动开发实践》,获出版社和作者授权共享。