设备驱动程序在linux内核中扮演着特殊的角色。它们是一个个独立的“黑盒子”,使某个特定硬件响应一个定义良好的内部编程接口,这些接口完全隐藏了设备的工作细节。用户的操作通过一组标准化的调用执行,而这些调用独立于特定的驱动程序。将这些调用映射到作用于实际硬件的设备特有操作上,则是设备驱动程序的任务。也就是说,应用软件工程师需要看到一个没有硬件的纯粹的软件世界,硬件必须被透明地呈现给他,谁来实现硬件对应用的硬件的隐形?就是驱动了。
设备驱动程序必须要“灵活”,即驱动程序的作用在于提供机制,而不是提供策略。区分机制和策略是Unix设计背后隐含的最好思想之一。大多数编程问题实际上都可以分成两部分:“需要提供什么功能”(机制)和“如何使用这些功能”(策略)。驱动程序同样存在机制和策略的分离问题,即要符合软件设计中的高内聚、低耦合的要求。
当没操作系统的时候,设备的驱动可以变得干净利落,而当系统中包含了操作系统后,驱动变成了连接硬件和内核的桥梁,操作系统的存在势必要求设备驱动附加更多的代码和功能,把单一的“驱使硬件设备行动”变成了操作系统内与硬件交互的模块,它对外呈现为操作系统的API,不再给应用软件工程师直接提供接口。也许有人会问,有了操作系统之后,驱动反而变得复杂,那要操作系统干什么?简而言之,操作系统通过给驱动制造麻烦来达到给上层应用提供便利的目的。当驱动都按照操作系统给出的独立于设备的接口而设计,那么,应用程序将可使用统一的系统调用接口来访问各种设备。
设备的分类:
字符设备:字符设备是个能够像字节流(类似文件)一样被访问的设备,由字符设备驱动程序来达到这种特性,可通过/dev下的节点来访问。
块设备:和字符设备类似,块设备也是通过/dev下的节点来访问。但是进行IO操作时块设备每次只能传输一个或多个完整的块。
网络接口:任何网络事务都经过一个网络接口形成,即一个能够和其他主机交换数据的设备。网络接口由内核中的网络子系统驱动,负责发送和接受数据包,但它不需要了解每项事务如何映射到实际传送的数据包。Unix访问网络接口的方法仍然是给他们分配一个唯一的名字(比如eth0),但这个名字在文件系统中不存在对应的节点。