你的位置:首页 > 操作系统

[操作系统]linux设备驱动第一篇:设备驱动程序简介


首先,我们知道驱动是内核的一部分,那么驱动在内核中到底扮演了什么角色呢?

设备驱动程序在内核中的角色:他们是一个个独立的“黑盒子”,使某个特定的硬件响应一个定义良好的内部编程接口,这些接口完全隐藏了设备的工作细节。(说白了,驱动程序除了对外提供特定的接口外,任何实现细节对应用程序都是不可见的。)用户的操作通过一组标准化的调用执行,而这些调用独立于特定的驱动程序。驱动程序的任务是把这些标准化调用映射到实际硬件的设备特有操作上。

在编写驱动程序时,程序员应该特别注意下面这个概念:编写访问硬件的内核代码时,不要给用户强加任何特定策略。这句话我的理解是,驱动只负责实现最基本的硬件功能,而谁使用此硬件,怎么使用,一般都不做考虑。

不带策略的驱动程序包括一些典型的特征:同时支持同步和异步操作、驱动程序能够被多次打开、充分利用硬件特性,以及不具备用来“简化任务”的或提供与策略相关的软件层等。

驱动程序就是应用程序与实际硬件之间的一个软件层,相同的硬件,不同的驱动程序可能提供不同的功能。实际的驱动程序设计要在许多要考虑的因素之间做出平衡。总的来说,驱动程序设计主要还是综合考虑下面三个方面的因素:提供给用户尽量多的选项、编写驱动程序要占用的时间以及尽量保持程序简单而不至于错误丛生。

了解了驱动在内核中扮演的角色,我们还可以简单了解下内核中包含的其他模块。一般把内核功能分成如下几部分:进程管理、内存管理、文件系统、设备控制、网络功能。操作系统原理上面把操作系统的原理分为:处理机管理、进程管理、文件管理、存储管理、设备管理、网络与通信管理、用户接口,其中处理机管理归根到底其实就是进程管理。因为处理器的分配和执行都是以进程为基本单位的。而存储管理就是说的内存管理。

进一步来看,电脑上有网卡,显卡,声卡等,还可以外接U盘,打印机等等外设,那么这么多的设备有没有分类呢?很明显,根据设备的接口,我们可以知道分为usb设备,串口设备,pci设备,spi设备,i2c设备等等,那么在linux内核中又有样的划分呢?下面所述就是linux中对所有设备的一个分类,并描述了相互之间的简单区别。

linux中设备和模块的分类:

字符设备:字符设备是能够像字节流(类似文件)一样被访问的设备,有字符设备驱动程序来实现这种特性。字符设备驱动程序通常至少要实现open、close、read、write系统调用。字符设备可以通过文件系统节点来访问,这些设备文件和普通文件之间的唯一差别在于对普通文件的访问可以前后移动访问位置,而大多数字符设备是一个只能顺序访问的数据通道。一个字符设备是一种字节流设备,对设备的存取只能按顺序按字节的存取而不能随机访问,字符设备没有请求缓冲区,所有的访问请求都是按顺序执行的。但事实上现在一些高级字符设备也可以从指定位置一次读取一块数据。

块设备:块设备也是通过设备节点来访问。块设备上能够容纳文件系统。在大多数unix系统中,进行I/O操作时块设备每次只能传输一个或多个完整的块,而每块包含512字节(或更2的更高次幂字节的数据)。linux可以让应用程序向字符设备一样读写块设备,允许一次传递任意多字节的数据。因而,块设备和字符设备的区别仅仅在于内核内部管理数据的方式,也就是内核及驱动程序之间的软件接口,而这些不同对用户来讲是透明的。在内核中,和字符驱动程序相比,块驱动程序具有完全不同的接口。存储设备一 般属于块设备,块设备有请求缓冲区,并且支持随机访问而不必按照顺序去存取数据,比如你可以 先存取后面的数据,然后在存取前面的数据,这对字符设备来说是不可能的。Linux下的磁盘设备都是块设备,尽管在Linux下有块设备节点,但应用程序一般是通过文件系统及其高速缓存来访问块设备的,而不是直接通过设备节点来读写块设备上的数据。

网络设备:网络设备不同于字符设备和块设备,它是面向报文的而不是面向流的,它不支持随机访问,也没有请求缓冲区。由于不是面向流的设备,因此将网络接口映射到文件系统中的节点比较困难。内核和网络设备驱动程序间的通讯,完全不同于内核和字符以及块驱动程序之间的通讯,内核调用一套和数据包传输相关的函数而不是read,write。网络接口没有像字符设备和块设备一样的设备号,只有一个唯一的名字,如eth0、eth1等,而这个名字也不需要与设备文件节点对应。

由上大致总结下字符设备与块设备的区别:1、字符设备是面向流的,最小访问单位是字节;而块设备是面向块的,最小访问单位是512字节或2的更高次幂。2、字符设备只能顺序按字节访问,而块设备可随机访问。3、块设备上可容纳文件系统,访问形式上,字符设备通过设备节点访问,而块设备虽然也可通过设备节点访问,但一般是通过文件系统来访问数据的。

而网络设备没有设备节点是因为,网络设备是面向报文的,很难实现相关read、write等文件读写函数。所以驱动的实现也与字符设备和块设备不同。