Linux内核设备模型
Patrick Mochel <[email protected]>
translated by:leonardo1019
translated:2010年7月24日
Drafted 26 August 2002
Updated 31 January 2006
概述
~~~~
Linux内核驱动模型是旧内核中所有孤立的驱动模型的统一。它把一组数据和操作合并到全局的数据结构中,为设备和桥接器增加总线特定的驱动。
传统的驱动模型为它们所控制的设备生成一种树形结构(有事仅仅是链表),不同的总线之间没有一个统一。
现在的驱动模型提供了一种统一,通用的数据模型,来描述总线和该总线下的设备【所以说为你的设备设计一个好的数据结构非常重要】。这种统一总线模型包括:一组所有总线都通用的属性;和一组通用的回调函数,例如总线探测时设备的发现,总线关闭,总线电源管理等等。
通用设备和通用桥接器接口反应了现代计算机的目标:设备的即插即用能力,电源管理和热插拔。特别是Inter和Microsoft提出的设备模型(即APCI),确保x86平台下的所有总线的上的所有设备都能实现上述的要求。当然,虽然很多总线都能支持大多数的操作,但也并不是支持所有的操作。
底层接口
~~~~~~~~
通用数据区域被从独立的总线层移到通用数据结构中。这些区域还必须能都被总线层访问,有时也要被特定设备的驱动程序访问。
其他的总线层也最好做成PCI总线的所做的这样。
pci_dev结构体现在是这样的:
struct pci_dev {
...
struct device dev;
};
首先这个结构体是静态分配内存的。在发现设备时只分配一次。其次,这个结构体的最后一个成员,也能让程序员在总线驱动和全局驱动切换时不会弄混。
PCI总线层可以随意访问这个结构体中的域。它要完全理解pci_dev结构体和device结构体。独立的PCI设备驱动通常不会也不应该接触device结构体中的域,除非你有个超级令人信服的理由。
这种抽象是为了避免过度期间产生不必要的麻烦。如果device结构中的某个域的名字改了或删去了,那下面的驱动程序就不能用了;而如果仅仅由总线层访问device结构的,那只有修改总线层就行了。
【有一个通用的设备结构体struct device,可以被任何驱动使用,但是新的驱动模型要求只有总线层来使用struct device,并把它封装起来,供该总线上的设备驱动使用】
用户接口
~~~~~~~~
由于我们已经对系统中所有设备都有个层次的认识,把这种分层次的设备图提供给用户空间也就相对容易了。这已经由一个特殊的虚拟的文件系统(sysfs)完成了。我们可以在用户空间的任何地方,把整个sysfs文件系统挂载上。
在/etc/fstab中提供一个入口点就可以永久的挂载sysfs了:
none /sys sysfs defaults 0 0
或者在命令行通过手动的方式:
# mount -t sysfs sysfs /sys
当新设备插入到树结构中时,就会对应的创建一个目录。这个目录可能被写入到任何层——全局层,总线层,或设备层。
全局层(global layer)创建两个文件——'name' 和 'power',前一个自然是设备的名字,后一个报告设备当前的power state【我不知道是“电源状态”还是当前“权限”……】,也可以用来设置当前的power state。
对于探测总线时发现的设备,总线层都会为之创建许多文件。例如,PCI层会为每个PCI设备创建“irq”和“resource”文件。
特定设备的驱动也会在它的目录下生成一些文件来导出设备特定的数据或tunable interfaces【应该配置设备的接口吧……】
更多的sysfs目录布局请参考Documentation/filesystems/sysfs.txt。
【何时进行探测总线(bus probe)?】
【加中括号的部分不是原文中的内容,是我自己临时想到的备注,其中有一些疑问,也会有些理解上的错误,希望好心人能帮助我解答指正】