linux设备驱动
驱动程序英文全称Device Driver,也称作设备驱动程序。驱动程序是用于计算机和外部设备通信的特殊程序,相当于软件和硬件的接口,通常只有操作系统能使用驱动程序。
在现代计算机体系结构中,操作系统并不直接于硬件打交道,而是通过驱动程序于硬件通信。
设备驱动介绍
驱动程序是附加到操作系统的一段程序,通常用于硬件通信。
每种硬件都有自己的驱动程序,其中包含了硬件设备的信息。操作系统通过驱动程序提供的硬件信息与硬件设备通信。由于驱动设备的重要性,在安装操作系统后需要安装驱动程序,外部设备才能正常工作。
Linux内核自带了相当多的设备驱动程序,几乎可以驱动目前主流的各种硬件设备。
在同一台计算机上,尽管设备是相同的,但是由于操作系统不同,驱动程序是有很大差别的。但是,无论什么系统驱动程序的功能都是相似的,可以归纳为下面三点:
初始化硬件设备。
这是驱动程序最基本的功能,初始化通过总线识别设备,访问设备寄存器,按照需求配置设备地端口,设置中断等。
向操作系统提供统一的软件接口。
设备驱动程序向操作系统提供了一类设备通用的软件接口,如硬盘设备向操作系统提供了读写磁盘块、寻址等接口,无论是哪种品牌的硬盘驱动向操作系统提供的接口都是一致的。
提供辅助功能。
现代计算机的处理能力越来越强,操作系统有一类虚拟设备驱动,可以模拟真实设备的操作,如虚拟打印机驱动向操作系统提供了打印机的接口,在系统没有打印机制情况下仍然可以执行打印操作。
Linux内核模块
Linux内核模块是一种可以被内核动态加载和卸载的可执行程序。
通过内核模块可以扩展内核的功能,通常内核模块被用于设备驱动、文件系统等。如果没有内核模块,需要向内核添加功能就需要修改代码、重新编译内核、安装新内核等步骤,不仅繁琐而且容易保出错,不易于调试。
内核模块简介
Linux内核是一个整体结构,可以把内核想象成一个巨大的程序,各种功能结合在一起。当修改和添加新功能的时候,需要重新生成内核,效率较低。
为了弥补整体式内核的缺点,Linux内核的开发者设计了内核模块机制。
从代码的角度看,内核模块是一组可以完成某种功能的函数集合。
从执行的角度看,内核模块可以看做是一个已经编译但是没有连接的程序。
内核模块是一个应用程序,但是与普通应用程序有所不同,区别在于:
1.运行环境不同
内核模块运行在内核空间,可以访问系统的几乎所有的软硬件资源;普通应用程序运行在用户空间,可以访问的资源受到限制。这也是内核模块与普通应用程序最主要的区别。由于内核模块可以获得与操作系统内核相同的权限,因此在编程的时候应该格外注意,可能在用户空间看到的一点小错误在内核空间就会导致系统崩溃。
2.功能定位不同
普通应用程序为了完成某个特定的目标,功能定位明确;内核模块是为其他的内核模块以及应用程序服务的,通常提供的是通用的功能。
3.函数调用方式不同
内核模块只能调用内核提供的函数,访问其他的函数会导致运行异常;普通应用程序可能调用自身以外的函数,只要能正确连接就有运行。
设备驱动程序
设备驱动程序在内核中的角色:他们是一个个独立的“黑盒子”,使某个特定的硬件响应一个定义良好的内部编程接口,这些接口完全隐藏了设备的工作细节。(说白了,驱动程序除了对外提供特定的接口外,任何实现细节对应用程序都是不可见的。)用户的操作通过一组标准化的调用执行,而这些调用独立于特定的驱动程序。驱动程序的任务是把这些标准化调用映射到实际硬件的设备特有操作上。
在编写驱动程序时,程序员应该特别注意下面这个概念:编写访问硬件的内核代码时,不要给用户强加任何特定策略。这句话我的理解是,驱动只负责实现最基本的硬件功能,而谁使用此硬件,怎么使用,一般都不做考虑。
不带策略的驱动程序包括一些典型的特征:同时支持同步和异步操作、驱动程序能够被多次打开、充分利用硬件特性,以及不具备用来“简化任务”的或提供与策略相关的软件层等。
驱动程序就是应用程序与实际硬件之间的一个软件层,相同的硬件,不同的驱动程序可能提供不同的功能。实际的驱动程序设计要在许多要考虑的因素之间做出平衡。总的来说,驱动程序设计主要还是综合考虑下面三个方面的因素:提供给用户尽量多的选项、编写驱动程序要占用的时间以及尽量保持程序简单而不至于错误丛生。
为了解了驱动在内核中扮演的角色,我们还可以简单了解下内核中包含的其他模块。一般把内核功能分成如下几部分:进程管理、内存管理、文件系统、设备控制、网络功能。操作系统原理上面把操作系统的原理分为:处理机管理、进程管理、文件管理、存储管理、设备管理、网络与通信管理、用户接口,其中处理机管理归根到底其实就是进程管理。因为处理器的分配和执行都是以进程为基本单位的。而存储管理就是说的内存管理。
进一步来看,电脑上有网卡,显卡,声卡等,还可以外接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等文件读写函数。所以驱动的实现也与字符设备和块设备不同。