没有合适的资源?快使用搜索试试~ 我知道了~
首页第5章 VxWorks下设备驱动的内核结构层次《Vxworks设备驱动开发详解》
资源详情
资源评论
资源推荐

《VXWORKS 设备驱动开发详解》
作者:华清远见
第 5 章 VxWorks 下设备驱动的内核结构层次
本章简介
本章将介绍 VxWorks 下设备驱动的结构层次,首先介绍 I/O 子系统下维护的三
张表及相互之间的关系,而后对内核已有驱动支持进行说明,并介绍 VxWorks 下文
件系统的支持,最后讨论如何添加一个驱动到内核中。

专业始于专注 卓识源于远见
‐2‐
认识 VxWorks 设备驱动内核基本层次
从上一章内容我们知道,底层设备驱动并不直接对用户可见,还需要经过操作系统中间层作为“桥梁”
进行交互。这个操作系统中间层根据具体的应用可能又被分为几个子层次,我们将从用户层开始到底层硬
件设备之间的所有由内核提供的中间软件层称为内核驱动层次(注意:底层驱动也是内核的一部分)。
为了保持应用层用户程序的平台无关性,操作系统为应用层提供了一套标准的接口函数,这些接口函
数在所有的平台上都保持一致,只是随着平台的变化,底层驱动或接近驱动部分操作系统中间层可能会随
着调整。如此一来,可以使用户程序脱离平台,增加了应用层开发的效率,避免了重复编码。通用操作系
统下,将这套提供给应用层的标准接口函数从操作系统中独立出来,专门以标准库的形式存在,这样更进
一步增加了应用程序的平台无关性,平台之间的差别完全被操作系统屏蔽。
VxWorks 下也对应用层提供了一套标准文件操作接口函数,实际上与通用操作系统提供的一致,我们
将其称作为标准 I/O 库,VxWorks 下由 ioLib.c 文件提供。ioLib.c 文件提供如下标准接口函数:creat、open、
unlink、remove、close、rename、read、write、ioctl、lseek、readv、writev 等。VxWorks 操作系统区别于通
用操作系统的一个很大的不同点是:VxWorks 下不区分用户态和内核态,用户层程序可以直接对内核函数
进行调用,而无须使用指令中断之类的机制或者存在使用权限上的限制。所以,VxWorks 提供给应用层的
接口无须通过外围库的方式,而是直接以内核文件的形式提供。用户程序可以直接使用 ioLib.c 文件定义的
如上这些函数,这些函数名称与通用操作系统标准库下的函数名一致,是 VxWorks 对标准库的模拟。
由于是 VxWorks 内核提供,我们将 ioLib.c 文件中定义的如上这些函数看做是内核的一部分。ioLib.c
文件提供的函数仅仅是一个最上层的接口,其并不完成具体的用户请求,而是将请求进一步向其他内核模
块进行传递,位于 ioLib.c 模块之下的模块就是 iosLib.c。我们将 ioLib.c 文件称为上层接口子系统,将 iosLib.c
文件称为 I/O 子系统,注意二者的区别。上层接口子系统直接对用户层可见,而 I/O 子系统则一般不可见
(当然用户也可以直接调用 iosLib.c 中定义的函数,但一般需要做更多的封装,且违背了内核提供的服务
层次),其作为上层接口子系统与下层驱动系统的中间层而存在。如图 5-1 所示显示了内核驱动层次。
从图 5-1 中可以看出,I/O 子系统在整个驱动层次中起着十分重要的作用,其对下管理着所有类型的
设备驱动。换句话说,所有类型(包括网络设备)的设备都必须向 I/O 子系统进行注册方可被内核访问。
所以,在 I/O 子系统这一层次,内核维护着几个十分关键的数组用以对设备驱动、设备本身以及当前系统
文件句柄进行管理。
1.USB 设备驱动内核层次
对于 USB 设备,通过 USB I/O 层驱动与 I/O 子系统进行交互,而与底层的交互则通过 USB 栈完成,
HC 驱动即主机 USB 控制器驱动,VxWorks 内核提供 UHCI、OHCI、EHCI 三种标准 USB 主机控制器的驱
动支持,但是在嵌入式平台下有时会存在一个定制的 USB 主机控制器,此时可能需要编写底层 HC 驱动。

专业始于专注 卓识源于远见
‐3‐
应用层
上层接口子系统
(
ioLib.c
)
o
p
en
、
read
、
write
、
close
、
ioctl
、
...
I
/
O
子系统
(
iosLib.c)
iosOpen
、
iosRead
、
iosWrite
、
iosClose
、
iosIoctl
、
...
文件系统
字符设备驱动
字符设备
块设备驱动
块设备
TFFS
中间层驱动
Flash
驱动
Flash
设备
TTY
驱动
串口驱动
串口设备
USB I
/
O
层驱动
USB
栈
HC
驱动
USB
主机控制器
图 5-1 VxWorks 内核驱动层次
2.块设备驱动内核层次
块设备从当前应用来看,主要分为两大类:一类是长期以来使用的硬盘设备;另一类是 Flash 设备。
硬盘设备驱动支持通过一个文件系统中间层,这个中间层在操作系统中十分关键,其对硬盘数据进行管理,
提供硬盘数据的内核缓存区,避免频繁访问硬盘对整个系统性能造成非常不利的影响。对于硬盘这类块设
备,直接在文件系统层下通过一个硬盘驱动即可完成。另一类块设备是 Flash 设备,Flash 设备的最大特点
是擦除次数有限,且擦除单元一般都较大,花费时间长,必须在文件系统层与 Flash 驱动层之间插入一个
针对 Flash 设备这些特点的管理层,而且 Flash 设备每次写入的数据块相对硬盘设备都比较大,而在文件系
统的统一管理下,我们需要将 Flash 设备模拟成一个硬盘设备,故在文件系统层和 Flash 驱动层还需要一个
转换层(或称映射层),VxWorks 内核提供 TFFS(True Flash File System)中间层完成以上对 Flash 管理和
映射的功能。TFFS 中间层内部又进行分层,每层对应一个驱动文件,这一点在本书“Flash 驱动”一章将
有较详细的讨论。
3.字符设备驱动内核层次
字符设备即以字节流方式进行数据交互的设备,该类设备只能顺序读写数据,不能像块设备那样对
同一数据进行反复操作。如一个 ADC 设备,其接收外界检波器模拟信号,转换为数字信号,通过串行
接口将数据送给 CPU,此时就需要一个驱动对这个 ADC 设备进行驱动以获取转换后的数据。从图 5-1
的层次来看,这个驱动将直接工作在 I/O 系统的管理之下。
串口设备本身也是一个字符设备,但是由于串口的使用范围广,为了提高串口驱动的编程效率以及串
口数据的收发效率,VxWorks 内核将串口设备与一般的字符设备区别对待,其提供一个 TTY 中间层驱动
对串口数据进行管理(提供缓存)。TTY 驱动向 I/O 系统注册,底层串口设备驱动对 TTY 注册。从底层驱
动编程难易程度来看,TTY 中间层的加入并非显著降低了底层串口的编程难度,但是 TTY 中间层提供的
一个最关键的优点是极大地提高了数据收发的效率,而且也提供了很大的灵活性,如提供较多的选项用以
对串口设备进行控制。

专业始于专注 卓识源于远见
‐4‐
4.网络设备驱动内核层次
在第 4 章中,我们将设备类型从总体上分为了三类:字符设备、块设备和网络设备。其中字符设备和
块设备均由 I/O 子系统进行管理,而网络设备由于其特殊的工作方式,将由另一套用户层标准接口函数(套
接字函数)和内核网络栈进行支持。对于网络设备驱动的支持,现在使用较多的是 VxWorks 提供的 MUX
接口,在 MUX 接口下编写的底层网口驱动被称为增强型网口驱动(Enhanced Network Driver,END)。
网络设备内核驱动层次如图 5-2 所示。
图 5-2 网络设备内核驱动层次
网络数据由于其传输介质的不稳定性造成了网络设备内核驱动层次和应用层接口层的特殊性。网络编
程应用层接口函数被称为 Socket(套接字),其区别于其他所有的设备编程使用的标准接口函数。为了在
网络上两台主机之间通信,我们首先必须约定一个协议,这样发送方以这个事先约定好的协议封装数据,
接收方按这些协议进行解析,如此方能达到数据的传送,如果二者没有共同的协议作为约束,那么接收方
根本就无法知道接收的报文中哪些是数据,哪些是为了使报文到达接收方的帮助信息。所以,网络数据传
输从一开始就好设计好一套网络上所有的主机都必须遵守的通信协议。但是“一步到位”的协议设计方式
为后期的扩展带来了极大的不便,如果一个新的更有效的协议被发明,那么网络上所有主机的网络驱动都
要进行修改,所以网络协议从开始时就被设计为分层次的结构,每层使用本层上具有的协议对数据进行封
装。
最经典的当前使用范围最广的就是四层分层结构,从上到下依次为:应用层、传输层、网络层、链路
层。虽然 OSI 后来开发出了一个七层分层结构,但是基于四层分层结构的应用已经十分广泛。当然 OSI
也考虑到这一点,所以七层分层结构在核心层上(传输、网络、链路)设计成与四层分层结构兼容,这样
原先的四层实现只需在传输层实现之上插入一个模块,即可完成对七层的支持,目前几乎所有声称支持七
层分层结构的实现都是这样实现的。当然有些读者可能会有疑问,为何设计分这么多层?原因在于:
网络上传输一个报文不像主机内部传递一个报文,在网络上传输的报文首先要指定目的主机的 IP 地址
以及任务绑定的端口号,同时为了使得接收方可以验证报文的合法性,还需要加上发送主机的 IP
地址以及报文发送任务绑定的端口号。
网络接口设备接收报文并不以 IP 地址作为判断依据,IP 地址只是被操作系统网络栈实现代码使用,
网络接口设备使用硬件地址,在以太网下称为 MAC 地址,一般是 6B 长度的字符串。所以,为
了使一个主机能够从网络介质接收数据,报文中还必须提供网卡设备硬件地址。
为了共享网络,网络上每个主机每次发送的报文长度必须有限,然而用户层一次发送的数据并不关心
这一点,所以在发送报文前还必须对报文进行切割,将原先的一个报文切割成几个报文分批发送,
而在接收端又需要将这几个报文进行重组后发送给相关进程,这些都需要在不同的层次完成。

专业始于专注 卓识源于远见
‐5‐
网络传输介质是不稳定的,可能有报文的丢失,不同的报文可能经过不同的传输路径到达,故一个先
发送的报文可能后到达等,这些问题都需要接收双方进行考虑。所有的网络栈必须设计成多个层
次,每个层完成不同的功能,如果所有的功能都集中在一起实现,那么代码将很复杂且不易维护
和修改。分成多层可以在每层实现特定的功能,且在后期加入一个新的功能也较容易,不会对其他
层的实现造成明显的影响。网络栈中“栈”的概念就是起源于操作系统对于网络报文的收发使用分
层的结构。
网络栈的实现是操作系统实现的一个固定组成部分,VxWorks 在基本的网络栈实现之下还实现了一个
MUX 接口层,专门与底层网络设备驱动进行交互。MUX 接口层将底层网络设备驱动与核心网络栈实现隔
离开来,其提供的接口函数极大地降低了底层网络设备驱动设计的复杂度,因为 MUX 层本身提供了一系
列函数对网络栈的请求进行了响应,而且也提供一些辅助函数供底层驱动进行调用,帮助进行一些辅助功
能的实现。VxWorks 将在 MUX 接口下实现的网络设备驱动称为 END 驱动,以区别于早期版中的 BSD 驱
动,即直接实现在 BSD 网络栈下的网络设备驱动。
网络传输方式下,由于需要对传输的数据经过分层次的特殊的封装,且需要对网络上两台主机之间通
信的不稳定性进行处理,故网络设备并不工作在 I/O 子系统下,而是使用完全不同的另一种机制,包括应
用层接口函数都是独立的一套函数集合。当然这种工作方式并非是 VxWorks 特有的,所有的操作系统对于
网络设备编程都采用与其他设备(字符和块设备)不同的方式。当然所有的平台对于网络设备的处理都是
基本一致的:应用层采用 Socket 编程接口,操作系统提供网络栈实现和网络设备驱动。
VxWorks 内核驱动基本结构——
内核三张表
由于 I/O 子系统在整个驱动层次中起着管理的功能,其维护着系统设备和驱动的关键的三张表。故本
节着重介绍 I/O 子系统层次的相关数据结构。
我们以一个字符设备为例,假设已经将该字符设备的驱动向 I/O 子系统进行了注册,并创建了一个该
字符设备的文件节点。下面以用户打开设备操作为例,介绍用户层请求传递到底层驱动的调用流程。
用户在使用一个设备之前,必须先打开该设备。以字符设备的文件节点为路径名调用 open 函数,open
函数将请求转移给 iosOpen。I/O 子系统维护着当前系统所有的驱动和设备。故其根据 open 函数调用时传
入的设备节点名从系统设备列表中查询设备,查询到设备后,由设备结构中的相关字段值得知该设备对应
的驱动程序索引号,I/O 子系统根据该驱动程序号从系统驱动列表中获取该设备对应的驱动函数集合,调
用底层驱动 open 响应函数,底层驱动 open 响应函数将进行中断注册,使能硬件工作,完成用户层打开设
备的服务请求。
open 函数返回一个整型数,我们将其称为文件描述符,I/O 子系统除了系统驱动和系统设备两张表外,
其维护的第三张表就是系统当前打开的所有的文件描述符表,该表中每个表项都是一个数据结构,表项在
表中的位置索引号就是文件描述符本身,而表项的内容则表明了该文件描述符对应的设备以及驱动。此后
对设备的读写、控制、关闭或其他任何操作将以文件描述符为依据。由文件描述符可以直接寻址到被操作
设备的驱动程序。
5.2.1 系统设备表
VxWorks 内核对每个设备使用 DEV_HDR 数据结构进行表示,该结构定义如下。
/*h/iosLib.h*/
typedef struct /* DEV_HDR - device header for all device structures */
{
DL_NODE node; /* device linked list node */
short drvNum; /* driver number for this device */
char * name; /* device name */
剩余25页未读,继续阅读













安全验证
文档复制为VIP权益,开通VIP直接复制

评论2