基本概念:
1.硬驱动与软驱动
前者是与硬件设备挂钩的,后者只是拓展了内核,作为了内核一部分
2.I/O系统
包括:I/O管理器,PNP,power
3.I/O设备:
一般能分为块设备(数据块作为通信介质),字符设备(数据流作为通信介质). 还有其他类型的
4.os如何控制设备?
通过与该设备上的控制器和总线
5.设备控制器
包含: 状态,命令寄存器. os通过这些寄存器操作硬件. 可供读写的buffer
6.cpu定义了地址空间,I/O端口空间. 指令In,out操作端口
7.设备控制器通过中断通知cpu此时的状态. cpu对其做相应处理
8.I/O软件
设备驱动程序:将os功能需求解释成针对该设备的请求,操作设备处理请求.返回结构给os
9.设计I/O驱动需要考虑:
实现异步通信
缓冲区管理
共享和独占设备
设备的状态管理:包括初始化,power管理,pnp管理,错误处理
10.i/o系统结构
i/o管理器,pnp管理器,power管理器,wmi例程. 设备驱动程序.
11.windows层次驱动模型
多个驱动程序协同完成I/O任务,I/O请求发到设备栈,栈顶首先处理该请求,然后依次向下传递,知道I/O请求完成
通常与硬件相关的驱动位于设备栈底,各个驱动程序只需关注自己任务.不用包揽所有I/O请求处理任务
I/O管理器
在I/O系统中3个基本内核对象:驱动程序,设备对象,文件对象
驱动程序和服务安装时指定了一个启动类型,存放在注册表(HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServices)中
#define SERVICE_BOOT_START 0x00000000 //由ntldr程序加载到系统空间
#define SERVICE_SYSTEM_START 0x00000001//
#define SERVICE_AUTO_START 0x00000002
#define SERVICE_DEMAND_START 0x00000003
#define SERVICE_DISABLED 0x00000004
驱动设备对象和设备对象
系统类驱动对象放置在FileSystem目录下, 其他在Driver目录下
设备对象:描述了一个特定设备的状态信息,包括收到的I/O请求,设备电源特性
NextDevice单链表的下一个设备对象
AttachedDevice和AttachedTo构成一个双链表前后指针
如图:图中上面为栈顶,下面为栈底. 说明了对于一个硬件设备,它的设备对象在该设备栈的栈底,I/O消息最后收到.设备栈中,不同的设备不一定是同一个驱动
对象创建的,可以是不同的驱动对象创建的设备对象附加到该设备栈顶.
驱动对象与设备对象关系:
驱动程序在初始化例程创建设备对象, 每个设备对象都有一个为它负责的驱动程序.
驱动程序的分发函数:当I/O管理器收到一个I/O请求时,根据请求中的信息来找到设备对象的驱动程序对象并调用驱动程序的相应
分发函数处理
文件对象
windows I/O系统提供给应用程序的I/O操作的目标对象是文件对象,代表设备对象的已打开实例. 内核或应用程序每打开一个设备对象就得到一个文件
对象. 文件对象也是一个内核对象.用户层代码通过句柄引用文件对象.例如设备对象的文件对象名称: Device 目录下
文件对象,驱动对象,设备对象关系图:
打开文件对象流程:
设备对象的删除
当一个设备对象引用计数减到0时将自动调用相应的删除函数IopDeleteDevice.且驱动对象的引用计数-- 当一个驱动对象的设备对象不为0时就不会删除掉
其次当驱动程序被卸载时,驱动程序初始化失败时,相应的设备被移除时,就算引用计数>0.将调用IoDeleteDevice函数删除之.
PnP管理器
职责:自动检测设备的插入和移除.动态分配硬件资源.指示I/O管理器为设备正确加载驱动程序.可以通过用户搜索驱动程序,通知设备插入和移除.
要求:
流程:
电源管理器
.......................
IRP
当内核模式代码要发起一个I/O请求时会构造一个irp,代表该I/O请求
创建:IoAllocateIrp->pIoAllocateIrp->IoAllocateIrpPrivate
释放:IoFreeIrp
特点:
所有I/O请求都是针对文件对象的操作,OriginalFileObject记录了该文件对象,代表I/O请求的目标
栈单元
支持取消
I/O请求的完成.驱动的分发函数处理完irp后需要显示通知I/O管理器
irp,文件对象,驱动程序,分发函数之间关系图:
来自用户层的I/O请求图:
基本流程:通过CreateFile创建指向目标设备对象的文件对象, 通过DeviceIoControl向设备对象发出I/O请求.最后CloseHandle
针对设备栈的I/O处理
I/O管理器将控制权交给驱动程序,此IRP对象就将在多个驱动程序之间进行流转,每个参与处理的驱动程序负责其中一部分,然后转交给下一个设备对象的驱动程序处理
本设备对象的驱动程序移交I/O请求:
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetComletionRoutine(Irp,ComletionRoutine,ContextInfo,InvokeOnSuccess,InvokeOnError,InvokeOnCancel);//将当前驱动程序使用的栈单元复制到下一个驱动程序要使用的栈单元.
//并注册一个完成函数,当I/O请求完成时可以干一些事.
status=IoCallDriver(NextLowerDevice,Irp);//将控制权交给下一级设备对象的驱动程序的分发函数.即当调用IoCompleteRequest()完成I/O后,从栈底到栈顶依此向上调用完成函数
如果不注册完成函数可以
IoSkipCurrentIrpStackLocation(Irp);//不保留栈单元
status=IoCallDriver(NextLowerDevice,Irp);
return status;
当驱动程序处理IRP时需要向底层发送多个I/O请求才能完成自己的处理时需要创建一组关联IRP.设置好与原IRP的关系然后逐个调用IoCallDriver
I/O完成端口