在派遣函数中可以调用IoCompleteRequest函数来结束IRP的处理或者调用IoMarkIrpPending来暂时挂起IRP,将IRP进行异步处理。...一般的IRP_MJ_CLOSE用来关闭内核创建的内核对象,对应用层来说也就是句柄,而IRP_MJ_CLEANUP用来处理被挂起的IRP,所以在这我们需要对CLEANUP的IRP进行处理,在处理它时,我们从链表中依次取出...在处理IRP时除了调用IoCompleteRequest结束之外还可以调用IoCancelIrp来取消IRP请求。...IoReleaseCancelSpinLock(Irp->CancelIrql); } //IRP_MJ_READ 处理 case IRP_MJ_READ: { Irp->IoStatus.Information...IRP对应的IRQL,所以这里直接传入Irp->CancelIrql
设备节点driverNode,对应不同的设备资源PCI、USB等 设备树,pnp管理的设备内部维护一个动态树 设备堆栈driverStack,fdo、pdo、do组成设备栈(devtree的单个分支),irp...分层模型 driver_object(结构未开放)和device_object,driver包含多个device对象的链表 device包含多个文件对象file_object file_object接收多个irp...irp的目标是driverObject的成员FileObject,指向各个设备文件 startio(设备忙排队等待)和多线程 irp状态决定了io状态,同步io、异步io、延迟io,IoCompleteRequest...调用IoComplete函数 内存指针MdlAddress 、AssociatedIrp、SystemBuffer IoStartPacket、IoStartNextPacket遍历irp调用startio...内核源码,使用内核工具编译成模块,系统启动后用insmod命令添加模块(.ko),在不需要的时候用rmmod命令卸载模块 linux的三个基本构件是:引导系统(boot loader), linux内核
本文并不是在说Linux系统总体上很卡顿,而只是说Linux系统桌面版的GUI程序相比Winddows很卡顿,如果真觉得本文是在喷Linux,那就当是喷Linux桌面的吧。...This is used by CD-ROM device // and file system drivers when completing an IRP (IoCompleteRequest) /...This is used by disk device // and file system drivers when completing an IRP (IoCompleteRequest) //...This is used by the mail- // slot file system driver when completing an IRP (IoCompleteRequest). //...This is used by the // named pipe file system driver when completing an IRP (IoCompleteRequest). //
目录 IRP 派遣函数 与通信方式 一丶IRP 1.1 IRP介绍 理论知识 1.2 IRP的类型 1.3 派遣函数 1.4 设备对象 与符号链接 1.5 IRP堆栈介绍 1.6 派遣函数中的IRP处理...1.2 IRP的类型 当应用层调用 ReadFile WriteFile CreateFile CloseHandle 等WINAPI 函数 则会产生对应的IRP类型的的IRP 也就是 IRP_MJ_CREATE...IRP_MJ_WRITE IRP_MJ_READ IRP_MJ_CLOSE 并且传送到驱动的中的派遣函数中。...IRP类型 来源 IRP_MJ_CREATE CreateFile/ZwCreateFile IRP_MJ_READ ReadFile/ZwReadFile IRP_MJ_WRITE WriteFile...否则操作系统就会将IRP再转发到设备栈的下一层设备进行处理。如果设备依旧不能处理,那么继续往下发。 因此IRP会被转发多次。为了记录IRP在每层设备中的操作,IRP会有一个堆栈数组。
: case IRP_MN_QUERY_REMOVE_DEVICE: case IRP_MN_QUERY_STOP_DEVICE: case IRP_MN_CANCEL_REMOVE_DEVICE...: case IRP_MN_CANCEL_STOP_DEVICE: case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: case IRP_MN_STOP_DEVICE...: case IRP_MN_QUERY_DEVICE_RELATIONS: case IRP_MN_QUERY_INTERFACE: case IRP_MN_QUERY_CAPABILITIES...: case IRP_MN_READ_CONFIG: case IRP_MN_WRITE_CONFIG: case IRP_MN_EJECT: case IRP_MN_SET_LOCK...: case IRP_MN_READ_CONFIG: case IRP_MN_WRITE_CONFIG: case IRP_MN_EJECT: case IRP_MN_SET_LOCK
IRP与派遣函数 IRP IRP(I/O Request Package)输入输出请求包,IRP的两个最基本的结构是MajorFunction和MinorFunction,分别记录IRP的主要类型和子类型...ZwCreateFile会产生IRP_MJ_CREATE类型的IRP。...下面是不同操作所对应产生的IRP请求列表 IRP类型 来源 IRP_MJ_CREATE 创建设备,CreateFile会产生此IRP IRP_MJ_CLOSE 关闭设备,CloseHandle会产生此IRP...IRP_MJ_CLEANUP 清除工作,CloseHandle会产生此IRP IRP_MJ_DEVICE_CONTROL DeviceIoControl函数会产生此IRP IRP_MJ_PNP 即插即用消息...会产生此IRP IRP_MJ_READ 读取设备内容,ReadFile会产生此IRP IRP_MJ_SET_INFORMATION 设置文件长度,SetFileSize IRP_MJ_SHUTDOWN
在Ring-3与Ring-0通讯方面,操作系统为每一个用户请求打包成一个IRP(IO Request Packet)结构,将其发送至驱动程序并通过识别IRP中的PDO来识别是发送给哪一个设备的。...2.3 IRP处理 I/O请求包IRP是驱动程序操作的中心,IRP是一个内核对象,它是预先定义好的数据结构,带有一组对它进行操作的I/O管理器例程,I/O管理器接受一个I/O请求,然后将它传送到合适的驱动程序栈中的最高驱动程序之前...,分配并处始化一个IRP,每个I/O请求有主功能代码 2.4 IRP参数比如一个写的I/O请求转换成一个IRP时,I/O管理器填写主要的IRP首部,并构造第一个个栈单元,对写请求来讲,首部包含用户缓冲区信息...,IRP由IRP首部和一系列的栈单元组成,每个栈单元是一个IO_STACK_LOCATION结构,首部和栈单元指出要作的动作 ,栈中有主要的重要参数如MajorFunction和MinorFunction...2.7 即插即用驱动必须有AddDevice例程并处理各种PnP IRP:IRP_MN_START_DEVICE分配资源并启动一个设备。
API调用的基本流程 一般在某些平台上进行程序开发,都需要使用系统提供的统一接口,linux平台直接提供系统调用,而windows上提供API,这两个并不是同一个概念(之前我一直分不清楚),虽然它们都是系统提供的实现某种功能的接口...的简介 R3与R0的通信是通过IRP进行数据的交换,IRP的定义如下: typedef struct DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) _IRP {...; IRP主要分为两部分,一部分是头,另一部分是IRP栈,在上一篇分析驱动中的数据结构时,说过驱动设备时分层的,上层驱动设备完成后,需要发到下层驱动设备,所有驱动设备公用IRP的栈顶,但是每个驱动都各自有自己的...IRP栈,它们的关系如下如所示: ?...->MajorFunction[IRP_MJ_WRITE] = IoDispatchWrite; pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL
暴力删除就是这里所讲的 IRP删除.给底层发送IRP即可进行删除文件. 1.步骤 步骤很简单.基本上说完就可以自己写代码做出 1.打开文件.获取文件句柄 (IoCreateFile) 2.根据文件句柄,...) 4.申请IRP(IoAllocateIrp) 5.初始化你申请的IRP 6.获取IRP的下层堆栈,并且初始化信息....(IoGetNextIrpStackLocation) 7.设置回调.系统完成IRP之后会调用你这个回调.所以你需要设置事件同步跟你自己同步,才知道IRP已经发送完了...., PVOID Context ) { //操作系统会设置这个回调 Irp->UserIosb->Status = Irp->IoStatus.Status; Irp...(PFILE_OBJECT pFileObj) { /* 1.申请IRP,初始化IRP 2.初始化同步事件,以及设置回调. 3.设置文件属性为默认 4.发送IRP
串口设备接收到的都是IRP请求.所以我们需要对IRP请求做过滤即可. 而串口过滤的时候我们只关心两种请求, 1.读请求. 2.写请求. 而过滤IRP请求则要关心他的功能号. ...IRP请求的有主功能号跟次功能号. 相应的在IRP栈空间中.会有一个字节保存了这些功能号....( IN PIRP Irp ); 参数.IRP结构体 通过IRP结构.获取当前IRP堆栈空间....在IRP结构中有三个缓冲区. 1.irp->MdlAddress 2.irp->UserBuffer 3.irp->AssociatedIrp.SystemBuffer; 关于IRP结构中的是哪个成员我们可以做一次解析...以及获取IRP堆栈. 获取IRP Buffer空间.那么我们则可以进行写代码了.
并记录当前挂起的IRP,然后在IRP_MJ_CLEARN请求中来完成挂起的IRP请求. 此时因为操作系统自身的机制.会设置ring3初始化的事件....这点和 IRP 同步与异步一篇中讲解的 IRP超时处理是一样的,唯一不同的就是超时处理是取消IRP. 而我们这里是完成IRP. 其中这里只提供DriverB的两个核心处理函数....三丶高级驱动程序调用IRP方式 3.1 设备调用方式-同步调用 3.1.1 IRP方式调用简介 所谓IRP方式就是自己申请IRP 然后发送IRP请求去调用DriverB程序 也就是说让我们自己实现 ZwCreateFile...IRP_MJ_WRITE IRP_MJ_PNP IRP_MJ_FLUSH_BUFFERS IRP_MJ_SHUTDOWN 通过这些功能号也就知道变相的等于一个函数顶替了几个函数....( [in] PIRP Irp ); 通过IRP返回他的下一层的堆栈.因为要模拟调用.所以我们要必须填写IRP的结构.
在完成例程中解析穿回来的IRP就可得到对应键盘的信息。...IRP数量都需要减一 g_KeyCount--; if(Irp->PendingReturned) { IoMarkIrpPending( Irp );...} return Irp->IoStatus.Status; } NTSTATUS c2cReadDispathc( IN PDEVICE_OBJECT DeviceObject..., IN PIRP Irp ) { PIO_STACK_LOCATION pIroStack; DbgPrint("Hook By Me!...,它注册的完成函数没有被调用,我也不知道为什么 pIroStack = IoGetCurrentIrpStackLocation(Irp); pIroStack->Control =
传输类型 位置 METHOD_IN_DIRECT irp->AssociatedIrp.SystemBuffer METHOD_OUT_DIRECT irp->AssociatedIrp.SystemBuffer...传输类型 位置 METHOD_IN_DIRECT irp->MdlAddress METHOD_OUT_DIRECT irp->MdlAddress METHOD_BUFFERED irp->AssociatedIrp.SystemBuffer...RequestorMode = KernelMode, the Irp->AssociatedIrp.SystemBuffer and Irp->UserBuffer fields do not contain...) { Irp->IoStatus.Information = 0; Status = Irp->IoStatus.Status = STATUS_UNSUCCESSFUL...= Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; break; } } IoCompleteRequest(Irp
比如你对IRP堆栈进行了操作....在IRP派遣函数中我们不想处理的数据可以通过记录在设备扩展中的目标设备对象,转发IRP进行执行. 在驱动卸载的时候也要进行解除附加....要给那个IRP设置完成例程(也就是给IRP的子域CompletionRoutine设置) 参数2: 完成例程的回调函数....参数4: 指定是否IRP被成功完成后进入完成例程 参数5: 指定是否IRP被错误完成后进入的完成例程 参数6: 是否是IRP被取消后......因此完成例程可以作为通知IRP完成的标志. 并且可以很清楚的知道IRP的完成情况. 4.3 完成例程的巧用 完成例程可以知道IRP的完成情况.
IRP请求会发送给设备对象.然后驱动对象会捕获.通过分发函数进行处理. 一个驱动对象可以有多个设备对象. 在内核中. 有驱动对象.设备对象. 以及IRP请求....This IRP is an associated IRP....; 其中IRP注意的事项....因为IRP发送给设备对象请求.所以有多个设备对象.而IRP结构体是固定的.所以在操作的时候.会有一些变动的参数.为了存储这些变动的参数....所以IRP结构体中保存了当前IRP堆栈.如果获取这些变动的参数.可以通过IRP堆栈来操作. 其中: CurrentLocation表示的当前是哪一个IRP堆栈.
与 IRP_MJ_WRITE这两个派遣函数,在派遣函数内则可以对收到的数据进行各类处理。...首先需要实现初始化各类派遣函数这么一个案例,如下代码则是通用的一种初始化派遣函数的基本框架,分别处理了IRP_MJ_CREATE创建派遣,以及IRP_MJ_CLOSE关闭的派遣,此外函数DriverDefaultHandle...] = DispatchCreate; // 创建派遣函数pDriver->MajorFunction[IRP_MJ_CLOSE] = DispatchClose; // 关闭派遣函数/.../ 增加派遣处理pDriver->MajorFunction[IRP_MJ_READ] = DispatchRead; // 读取派遣函数pDriver->MajorFunction[IRP_MJ_WRITE...*Irp){NTSTATUS Status = STATUS_SUCCESS;PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
函数会产生此IRP),MinorFunction 为自己定义的控制码的IRP,系统就调用相应的处理IRP_MJ_DEVICE_CONTROL的派遣函数,你在派遣函数中判断MinorFunction ,是自定义的控制码你就进行相应的处理...) { Irp->IoStatus.Status = STATUS_SUCCESS; //LastError() Irp->IoStatus.Information = 0;...//ReturnLength IoCompleteRequest(Irp, IO_NO_INCREMENT); //将Irp返回给Io管理器 return...= Irp->AssociatedIrp.SystemBuffer; OutputData = Irp->AssociatedIrp.SystemBuffer; InputDataLength...; IoCompleteRequest(Irp, IO_NO_INCREMENT); //将Irp返回给Io管理器 return Status;
; ///设置状态为STATUS_SUCCESS 即成功 p_Irp^.IoStatus.Information := 0; IofCompleteRequest(p_Irp, IO_NO_INCREMENT...); ///调用IoCompleteRequest完成IRP Result := STATUS_SUCCESS; end; function KernelTerminateThreadRoutine(...); {取IRP的stack location的指针} dwIoControlCode := psl^.Parameters.DeviceIoControl.IoControlCode; ///取控制码...^.IoStatus.Status := status; p_Irp^.IoStatus.Information := dwBytesReturned; IofCompleteRequest(p_Irp...] := @DispatchCreateClose; ///这里把IRP_MJ_CREATE IRP_MJ_CLOSE设置到一个函数上 pDriverObject^.MajorFunction[IRP_MJ_CLOSE
领取专属 10元无门槛券
手把手带您无忧上云