【IT168 专稿】本文将为读者详细介绍驱动程序的实现方法。我们首先介绍驱动程序的任务,并继续探讨缓冲区的处理、内存地址重建及调试域等。
1.驱动程序的任务
实际上,驱动程序的实现方法有多种,具体采用哪种,在很大程度上要取决于设备的类型以及有关要求。举例来说,开发工具附带的网卡调试驱动程序大多数都工作在轮询模式下,但是对于常规网络驱动程序来说,通常这是不能接受的。
下面我们考察一个利用中断的驱动程序的实现。在Windows Embedded CE系统中,中断是由中断服务例程(ISR)和中断服务线程(IST)进行处理的。ISR例程属于OAL层的组成部分。此外,如果支持被归入OAL层,它们就可以在执行期间(安装型ISR例程—IISR)安装。ISR例程的主任务包括确定中断源、屏蔽中断以及返回逻辑系统中断(SYSINTR)标识符。IST则是一个跑腿的,大部分的中断处理工作都是它完成的。它生成一个事件,在内核中将该事件注册为某种逻辑中断,然后就开始等待该事件的出现。当事件发生时,它会对其进行所有必要的处理工作。如果一个驱动程序使用了安装型ISR,那么IST就会加载这个安装型例程;如果一个驱动程序使用多个线程实现,那么当一个线程在等待和处理一个事件时,同时还可以在另一个线程中完成ISR的创建和安装过程。驱动程序的任务包括以下内容:
确定中断的系统标识符:
·可以直接在驱动程序中规定。
·可以利用DDKReg_GetIsrInfo()函数从注册表项中获得。
·可以利用IRQ–IOCTL_HAL_REQUEST_SYSINTR 向OAL层发送请求。
建立一个事件(CreateEvent())。
在内核中为该事件注册一个指定的中断的系统标识符(InterruptInitialize())。
利用WaitForSingleObject()等待一个事件。
事件发生后,对其进行相应的处理。
处理结束后,调用InterruptDone()。
如果驱动程序使用了安装型ISR例程,那么它还要完成下列任务:
确定ISR例程的设置(名称、入口点及其他参数):
·可以直接在驱动程序内部指定。
·可以利用DDKReg_GetIsrInfo()函数从注册表项中获得。
为特定IRQ请求装入一个已安装的IISR过程(LoadIntChainHandler())。
配置IISR过程(KernelLibIoControl())。
结束后,它会调用FreeintChainHandler()函数,该函数的作用是,当处理某个中断请求(IRQ)时,将在OAL层中调用的、已安装过程链中除去已安装的IISR过程。它会把这些库代码装载到内存中。
2.安装型ISR例程
安装型ISR例程是作为一个动态加载库来实现的,这个库必须满足以下要求:
·实现代码必须全部位于该库内部;不能存在显式的依赖性。
· 不存在隐式的依赖性(NOMUPS16CODE = 1)。
·不能使用C运行时库(NOLIBC = 1)。
3.通用安装型服务程序(GIISR)
通用安装型服务程序(GIISR)是一个已安装好的过程,用来处理各种常见的中断,随它一起提供的还有许多开发工具。GIISR为我们提供了源代码,位于\ Public\Common\Oak\Drivers\GIISR\,它适用于大多数的情况,并且会读取寄存器/端口以确定中断的状态。我们可以使用KernelLibIoControl配置GIISR过程,如下所示:
·寄存器地址/端口地址。
·寄存器长度/端口长度。
·功能部件、内存或者输入/输出寄存器或者端口。
·屏蔽。
4.与缓冲区有关概念
驱动程序开发的一个重要部分是从调用代码处理需要传递的缓冲区,下面是一些有关的概念。
·访问检验:对发起调用的进程进行检查,以确保它具备访问指定缓冲区的足够权限。
·指针参数:一个指针,将作为参数传给一个API函数。
·嵌入指针:指包含在数据结构或者缓冲区内部作为参数传递给API函数的指针。
·安全副本:已传送缓冲区数据的一个本地副本。
·内存地址重建或映射:通常也应用于指针,为将指针用于另一进程而做好准备。
·同步访问:当函数调用时, 在被调用线程中访问内存。