某些驱动可以为指定设备的多个实例提供服务。例如,串口通信设备的单个驱动可以处理多个分割的仅参数不同的通道,比如设备地址。在VxWorks的I/O系统中,设备用一个称之为设备头(DEV_HDR)的数据结构来定义,这个数据结构包含设备名字符串、服务这个设备的驱动设备号。在VxWorks的系统中,所有设备的设备头都常驻内存,并链成一个设备链表。设备头是特定驱动所确定的一个大的数据结构的起始部分,这个大的数据结构称之为设备描述符(device descriptor),设备描述符除了设备头之外,还包含诸如设备地址、缓冲区、信号量等与具体设备相关的成员。
VxWorks 内核对每个设备使用DEV_HDR 数据结构进行表示,该结构定义如下:
该结构中给出了链接指针(用来将该结构串入队列中)、驱动索引号、设备节点名等。这个结构较为简单,只存储了一些设备关键系统。底层驱动对其驱动的设备都有一个自定义的数据结构表示,最关键的一点是DEV_HDR内核结构必须是这个自定义的数据结构的第一个成员变量。我们的自定义数据结构如下:
之后为了能够让用户对设备进行操作,驱动必须要将设备注册到I/O子系统,这个过程也被称为是创建设备节点。I/O子系统提供iosDevAdd()函数用于被驱动调用来注册一个设备:
iosDevAdd()函数将一个设备添加到I/O子系统维护的系统的设备列表当中。该列表是一个队列,队列中的成员通过指针链接在一起,这是由DEV_HDR 结构中的node 成员变量完成的。系统设备列表由iosDvList内核变量指向,如图所示为系统设备列表示意图。
非块设备通过调用内部例程iosDevAdd()被动态添加到I/O系统中,iosDevAdd()的参数包含这个新设备的设备描述符地址、设备名字、以及服务该设备的驱动的驱动号。设备描述符是由驱动所指定的,其中包含必须的与设备相关的信息,但是必须以设备头作为该设备描述符的第一个成员。驱动不需要添加设备描述符的设备头部分,只需要填写设备描述符中与具体设备相关的信息。iosDevAdd()例程负责填写设备头中的设备名、设备号,并把该设备添加到系统设备链表中。下图展示一个驱动的设备创建例程xxxxDevCreate()通过调用iosDevAdd()添加一个设备到I/O系统当中: