Linux 的一个基本特征就是它抽象了设备的处理。 所有的硬件设备都与常规的文件十分相似,它们可以通过与操纵文件完全一样的标准,调用来打开、关闭、读和写,系统中的每个设备由一个特殊设备文件来表示。
Linux 支持三种硬件设备类型:字符设备、块设备和网络设备。 字符设备是支持无缓存读写的设备,块设备只能按块的大小进行读写,典型的块大小是512 B 或1 024 B。 块设备是通过缓冲区缓存来访问的,并支持随机访问,即无论该块在设备的何处,都能够直接读写,块设备能通过特殊设备文件来访问,但大多数情况下是通过文件系统来访问的,只有块设备才支持安装文件系统。 网络设备是通过BSD 套接字接口来访问的。
Linux 通过用主设备号和一组系统表格(如字符设备表),在系统调用中将特殊设备文件(假定在块设备的装配文件系统中)映射到设备的设备驱动程序上。
(1)设备驱动程序与内核的接口
Linux 内核可以按照一种标准的方式与驱动程序进行交互。 每类设备驱动程序、字符设备、块设备和网络设备,都为内核在使用它们的服务时提供相同的使用接口,这些相同的接口使得内核可以对完全不同的设备和专门的驱动程序按照完全相同的方式进行处理。
Linux 具有很高的动态性,每次Linux 内核启动时,会遇到不同的物理设备,需要不同的设备驱动程序。 Linux 允许在编译内核时,通过配置脚本将设备驱动程序加入到内核中,而这些驱动程序在启动初始化时,允许出现找不到要控制的硬件的情况。 其他的驱动程序可以在需要时作为内核的模块被载入。 为了实现设备驱动程序的动态性,设备驱动程序在初始化时要向内核注册,Linux 维护一个设备驱动程序表,并将它作为与驱动程序接口的一部分,这些表包括支持该类设备接口的例程和其他信息。
(2)设备驱动程序
设备驱动程序也是内核的一部分,它由一组数据结构和函数组成,其中的大部分函数是对驱动程序接口的实现,驱动程序通过这组数据结构和函数控制一个或多个设备,并通过驱动程序接口与内核的其他部分交互;然而,从很多方面来说,驱动程序不同于内核的其他部件并且独立于内核的其他部件。 驱动程序是与设备交互的唯一模块,通常由第三方厂商开发驱动程序,不与其他驱动程序交互;内核与驱动程序之间也仅通过一个严格定义的接口进行交互。 这种做法有许多好处:可以将设备专用代码分离到一个独立的模块中,便于添加新设备,用户或厂商可以在没有内核源码的情况下添加设备内核,可以对所有的设备一视同仁,通过相同的接口访问所有的设备。
Linux 有许多不同的设备驱动程序,这也是Linux 在嵌入式系统开发中广泛应用的原因之一,而且驱动程序还在不断增长。 虽然这些驱动程序驱动的设备不同和完成的工作各异,但它们都具有一些一般的属性。
1)Kernel code
设备驱动程序与内核中的其他代码相似,是Kene 的一部分,如果发生错误,可能严重害系统。 一个粗劣的驱动程序甚至可能摧毁系统,可能破坏文件系统,丢失数据。
2)Kenel interfaces
设备驱动程序必须向Linux 内核或它所在的子系统提供一个标准的接口,例如,终端。 驱动程序向Lnux 内核提供了一个文件I/0 接口,而SCSI 设备驱动程序向SCSI 子系统提供了SCSI 设备接口,接着,向内核提供了文件I/O 和buffer2cache 的接口。
3)Kernel mechanisms and services
设备驱动程序使用标准的内核服务,例如内存分配、中断转发和等待队列来完成工作。Unix SVR4 提供了设备——驱动程序接口/驱动程序/内核接口规范(DDI/DKI),由它来规范内核与驱动程序之间的接口。 该接口分为五个部分:①说明驱动程序应该包括的数据定义;②定义驱动程序入口点例程,包括接口函数、初始化、中断处理程序等;③说明可由驱动程序调用的内核例程;④说明驱动程序可能用到的内核数据结构;⑤包含驱动程序可能用到的内核# define 语句。
4)Loadable
大多数的Linux 设备驱动程序可以在需要时作为内核模块加载,当不再需要时就可卸载,这使得内核对于系统资源非常具有适应性和效率。
5)Configurable(www.xing528.com)
Linux 设备驱动程序可以建立在内核,至于哪些设备建立到内核,可以在内核编译时配置。
6)Dynamic
系统启动时,每一个设备启动程序初始化时,它会查找它管理的硬件设备,并且一个设备驱动程序所控制的设备不存在并没有关系。 这时,这个设备驱动程序只是多余的,占用很少的系统内存,而不会产生危害。
内核在下面几种情况下调用设备驱动程序:
①配置:内核在初始化时,调用驱动程序检查并初始化设备。
②I/O:内核调用设备驱动程序从设备读数据或向设备写数据。
③控制:向设备发出控制请求,让设备完成读/写以外的动作,例如打开或关闭设备。
④中断:当设备完成某个I/O 请求、设备接收到数据和设备状态改变时,它都会通过中断引起CPU 的注意,此时,内核使用驱动程序中的设备中断处理程序完成相应的中断处理。
一个设备驱动程序一般由下面几部分组成:
①对驱动程序接口函数的实现。 对于字符和块设备,要实现的接口函数定义在数据结构file_operations 中;对于网络设备,要实现的接口函数定义在数据结构device 中。 当然,一个动程序并不一定要实现接口中的所有函数。
②设备专有部分。 为了实现接口函数和对设备进行合理的管理,设备驱动程序还定义一些自己的数据结构和管理函数。
③中断处理程序。 一般的外设都要产生中断,而这些中断都要在设备驱动程序中处理。因此,驱动程序中要有中断处理程序。
④初始化函数。 在系统初始化时,它轮流调用各个设备驱动程序的初始化函数。 初始化函数向系统注册自身,并要完成对设备的初始化。
Linux 支持三种类型的硬件设备:字符、块和网络。
①字符设备能够存储或传输不定长数据,某些字符设备可以每次传递1 字节,传完每个字节后产生一个中断;另一些字符设备可以在内部缓存一些数据。 内核将字符设备看成可顺序访问的连续字节流,它在单个字符的基础上接收和发送数据。 字符设备不能以任意地址访问,也不允许查找操作。 字符设备有终端(键盘、显示器)、打印机、鼠标、声卡、系统的串行端口/dev/cua 0 和/dev/cua 1 等。
②块设备中存储的是定长且可任意访问的数据块,对块设备的I/O 操作只能以块为单位(一般是512 B 或者1 024 B)进行。 块设备有硬盘、软盘、光盘、磁带等。 块设备通过buffer cache 访问,可以随机存取;就是说,任何块都可以读/写,不必考虑它在设备的什么地方。 块设备可以通过它们的设备特殊文件访问,但是更常见的是通过文件系统进行访问。 只有一个块设备可以支持一个安装的文件系统。 Linux 文件系统只能建立在块设备上。
③网络设备是通过BSD socket 接口访问的设备。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。