首页 »编程综合 » reactos:reactos操作系统实现(87) »正文
reactos:reactos操作系统实现(87)
来源: 发布时间:星期一, 2009年9月28日 浏览:0次 评论:0
应用 ![](/icons/96537chengxu.gif) 对设备I/O进行Win32 ![](/icons/96537diaoyong.gif) ![](/icons/96537dou.gif) 这个 ![](/icons/96537diaoyong.gif) 由I/O系统服务接收 ![](/icons/96537dou.gif) 然后I/O管理器从这个请求构造 ![](/icons/96537yi.gif) 个合适 ![](/icons/96537de.gif) I/O请求包(IRP) ![](/icons/96537dou2.gif) 那么I/O管理器是如何样创建这个I/O请求包(IRP) ![](/icons/96537de.gif) 呢?又是如何样传送给驱动 ![](/icons/96537chengxu.gif) ![](/icons/96537de.gif) 呢?我们带着这两个问题来分析下面实现文件读取 ![](/icons/96537de.gif) 代码 ![](/icons/96537dou.gif) 如下: #001 NTSTATUS #002 NTAPI #003 NtReadFile(IN HANDLE FileHandle, #004 IN HANDLE Event OPTIONAL, #005 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, #006 IN PVOID ApcContext OPTIONAL, #007 OUT PIO_STATUS_BLOCK IoStatusBlock, #008 OUT PVOID Buffer, #009 IN ULONG Length, #010 IN PLARGE_INTEGER ByteOff OPTIONAL, #011 IN PULONG Key OPTIONAL) #012 { #013 NTSTATUS Status = STATUS_SUCCESS; #014 PFILE_OBJECT FileObject; #015 PIRP Irp; #016 PDEVICE_OBJECT DeviceObject; #017 PIO_STACK_LOCATION StackPtr; #018 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode ; #019 PKEVENT EventObject = NULL; #020 LARGE_INTEGER CapturedByteOff ; #021 ULONG CapturedKey = 0; #022 BOOLEAN Synchronous = FALSE; #023 PMDL Mdl; #024 PAGED_CODE ; #025 CapturedByteOff .QuadPart = 0; #026 IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle); #027
检查是否在用户模式 ![](/icons/96537diaoyong.gif) ![](/icons/96537dou2.gif) #028 /* Validate User-Mode Buffers */ #029 (PreviousMode != KernelMode) #030 { 使用SEH机制 ![](/icons/96537dou.gif) 以便截取异常 ![](/icons/96537dou2.gif) #031 _SEH2_TRY #032 { 检测状态块 ![](/icons/96537dou2.gif) #033 /* Probe the status block */ #034 ProbeForWriteIoStatusBlock(IoStatusBlock); #035 检查读取缓冲区 ![](/icons/96537dou2.gif) #036 /* Probe the read buffer */ #037 ProbeForWrite(Buffer, Length, 1); #038 #039 /* Check we got a off */ #040 (ByteOff ) #041 { #042 /* Capture and probe it */ #043 CapturedByteOff = ProbeForReadLargeInteger(ByteOff ); #044 } #045 #046 /* Capture and probe the key */ #047 (Key) CapturedKey = ProbeForReadUlong(Key); #048 } #049 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) #050 { #051 /* Get the exception code */ #052 Status = _SEH2_GetExceptionCode ; #053 } #054 _SEH2_END; #055 #056 /* Check for probe failure */ #057 (!NT_SUCCESS(Status)) Status; #058 } #059 ![](/icons/96537else.gif) #060 { #061 /* Kernel mode: capture directly */ #062 (ByteOff ) CapturedByteOff = *ByteOff ; #063 (Key) CapturedKey = *Key; #064 } #065
获取文件对象 ![](/icons/96537dou2.gif) #066 /* Get File Object */ #067 Status = ObReferenceObjectByHandle(FileHandle, #068 FILE_READ_DATA, #069 IoFileObjectType, #070 PreviousMode, #071 (PVOID*)&FileObject, #072 NULL); #073 (!NT_SUCCESS(Status)) Status; #074 检查事件是否响应 ![](/icons/96537dou2.gif) #075 /* Check for event */ #076 (Event) #077 { #078 /* Reference it */ #079 Status = ObReferenceObjectByHandle(Event, #080 EVENT_MODIFY_STATE, #081 ExEventObjectType, #082 PreviousMode, #083 (PVOID*)&EventObject, #084 NULL); #085 (!NT_SUCCESS(Status)) #086 { #087 /* Fail */ #088 ObDereferenceObject(FileObject); #089 Status; #090 } #091 #092 /* Otherwise re the event */ #093 KeClearEvent(EventObject); #094 } #095
检查是否使用同步I/O ![](/icons/96537de.gif) 方式 ![](/icons/96537dou2.gif) #096 /* Check we should use Sync IO or not */ #097 (FileObject->Flags & FO_SYNCHRONOUS_IO) #098 { 这里是使用同步模式 ![](/icons/96537dou2.gif) #099 /* Lock the file object */ #100 IopLockFileObject(FileObject); #101 #102 /* Check we don't have a off avilable */ #103 (!(ByteOff ) || #104 ((CapturedByteOff .u.LowPart FILE_USE_FILE_POINTER_POSITION) && #105 (CapturedByteOff .u.HighPart -1))) #106 { #107 /* Use the Current Byte Off instead */ #108 CapturedByteOff = FileObject->CurrentByteOff ; #109 } #110 #111 /* Remember we are sync */ #112 Synchronous = TRUE; #113 } #114 (!(ByteOff ) && #115 !(FileObject->Flags & (FO_NAMED_PIPE | FO_MAILSLOT))) #116 { 非法文件对象 ![](/icons/96537dou2.gif) #117 /* Otherwise, this was async I/O without a off , so fail */ #118 (EventObject) ObDereferenceObject(EventObject); #119 ObDereferenceObject(FileObject); #120 STATUS_INVALID_PARAMETER; #121 } #122
从文件里获取设备对象 ![](/icons/96537dou2.gif) #123 /* Get the device object */ #124 DeviceObject = IoGetRelatedDeviceObject(FileObject); #125 #126 /* Clear the File Object's event */ #127 KeClearEvent(&FileObject->Event); #128 分配 ![](/icons/96537yi.gif) 个读取文件 ![](/icons/96537de.gif) 请求包(IRP) ![](/icons/96537dou2.gif) #129 /* Allocate the IRP */ #130 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); #131 (!Irp) IopCleanupFailedIrp(FileObject, NULL, NULL); #132 设置IRP ![](/icons/96537de.gif) 属性 ![](/icons/96537dou2.gif) #133 /* Set the IRP */ #134 Irp->Tail.Overlay.OriginalFileObject = FileObject; #135 Irp->Tail.Overlay.Thread = PsGetCurrentThread ; #136 Irp->RequestorMode = PreviousMode; #137 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine; #138 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext; #139 Irp->UserIosb = IoStatusBlock; #140 Irp->UserEvent = EventObject; #141 Irp->PendingReturned = FALSE; #142 Irp->Cancel = FALSE; #143 Irp->CancelRoutine = NULL; #144 Irp->AssociatedIrp. Buffer = NULL; #145 Irp->MdlAddress = NULL; #146
设置IRP ![](/icons/96537de.gif) ![](/icons/96537diaoyong.gif) 栈 ![](/icons/96537dou2.gif) #147 /* Set the Stack Data */ #148 StackPtr = IoGetNextIrpStackLocation(Irp); #149 StackPtr->MajorFunction = IRP_MJ_READ; #150 StackPtr->FileObject = FileObject; #151 StackPtr->Parameters.Read.Key = CapturedKey; #152 StackPtr->Parameters.Read.Length = Length; #153 StackPtr->Parameters.Read.ByteOff = CapturedByteOff ; #154 检查设备对象是否使用缓冲I/O ![](/icons/96537de.gif) 方式 ![](/icons/96537dou.gif) 还是使用直接I/O ![](/icons/96537de.gif) 方式 ![](/icons/96537dou2.gif) #155 /* Check this is buffered I/O */ #156 (DeviceObject->Flags & DO_BUFFERED_IO) #157 { 使用缓冲I/O ![](/icons/96537de.gif) 方式 ![](/icons/96537dou.gif) 就分配非分页内存 ![](/icons/96537dou2.gif) #158 /* Check we have a buffer length */ #159 (Length) #160 { #161 /* Enter SEH */ #162 _SEH2_TRY #163 { #164 /* Allocate a buffer */ #165 Irp->AssociatedIrp. Buffer = #166 ExAllocatePoolWithTag(NonPagedPool, #167 Length, #168 TAG_SYSB); #169 } #170 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) #171 { #172 /* Allocating failed, clean up */ #173 IopCleanupAfterException(FileObject, Irp, EventObject, NULL); #174 Status = _SEH2_GetExceptionCode ; #175 } #176 _SEH2_END; #177 (!NT_SUCCESS(Status)) Status; #178 #179 /* Set the buffer and flags */ #180 Irp->UserBuffer = Buffer; #181 Irp->Flags = (IRP_BUFFERED_IO | #182 IRP_DEALLOCATE_BUFFER | #183 IRP_INPUT_OPERATION); #184 } #185 ![](/icons/96537else.gif) #186 { #187 /* Not reading anything */ #188 Irp->Flags = IRP_BUFFERED_IO | IRP_INPUT_OPERATION; #189 } #190 } #191 (DeviceObject->Flags & DO_DIRECT_IO) #192 {
使用直接I/O ![](/icons/96537de.gif) 方式 ![](/icons/96537dou.gif) 就创建内存描述符列表 ![](/icons/96537dou2.gif) #193 /* Check we have a buffer length */ #194 (Length) #195 { #196 _SEH2_TRY #197 { #198 /* Allocate an MDL */ #199 Mdl = IoAllocateMdl(Buffer, Length, FALSE, TRUE, Irp); #200 MmProbeAndLockPages(Mdl, PreviousMode, IoWriteAccess); #201 } #202 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) #203 { #204 /* Allocating failed, clean up */ #205 IopCleanupAfterException(FileObject, Irp, EventObject, NULL); #206 Status = _SEH2_GetExceptionCode ; #207 _SEH2_YIELD( Status); #208 } #209 _SEH2_END; #210 #211 } #212 #213 /* No allocation flags */ #214 Irp->Flags = 0; #215 } #216 ![](/icons/96537else.gif) #217 { #218 /* No allocation flags, and use the buffer directly */ #219 Irp->Flags = 0; #220 Irp->UserBuffer = Buffer; #221 } #222
设置读取 ![](/icons/96537de.gif) 标志 ![](/icons/96537dou2.gif) #223 /* Now the deferred read flags */ #224 Irp->Flags |= (IRP_READ_OPERATION | IRP_DEFER_IO_COMPLETION); #225 # 0 #226 /* FIXME: VFAT SUCKS */ #227 (FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) Irp->Flags |= IRP_NOCACHE; #228 #end![](/icons/96537if.gif) #229 ![](/icons/96537diaoyong.gif) ![](/icons/96537hanshu.gif) IopPerformSynchronousRequest把IRP发送给过滤驱动 ![](/icons/96537chengxu.gif) ![](/icons/96537dou.gif) 或者目标驱动 ![](/icons/96537chengxu.gif) ![](/icons/96537dou2.gif) #230 /* Perform the call */ #231 IopPerformSynchronousRequest(DeviceObject, #232 Irp, #233 FileObject, #234 TRUE, #235 PreviousMode, #236 Synchronous, #237 IopReadTransfer); #238 } #239 下面继续分析写文件 ![](/icons/96537de.gif) 操作 ![](/icons/96537hanshu.gif) ![](/icons/96537dou.gif) 就可以知道写文件时如何样发送I/O请求包 ![](/icons/96537dou.gif) 实现代码如下: #001 NTSTATUS #002 NTAPI #003 NtWriteFile(IN HANDLE FileHandle, #004 IN HANDLE Event OPTIONAL, #005 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, #006 IN PVOID ApcContext OPTIONAL, #007 OUT PIO_STATUS_BLOCK IoStatusBlock, #008 IN PVOID Buffer, #009 IN ULONG Length, #010 IN PLARGE_INTEGER ByteOff OPTIONAL, #011 IN PULONG Key OPTIONAL) #012 { #013 NTSTATUS Status = STATUS_SUCCESS; #014 PFILE_OBJECT FileObject; #015 PIRP Irp; #016 PDEVICE_OBJECT DeviceObject; #017 PIO_STACK_LOCATION StackPtr;
获取前 ![](/icons/96537yi.gif) 个内核模式 ![](/icons/96537dou2.gif) #018 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode ; #019 PKEVENT EventObject = NULL; #020 LARGE_INTEGER CapturedByteOff ; #021 ULONG CapturedKey = 0; #022 BOOLEAN Synchronous = FALSE; #023 PMDL Mdl; #024 OBJECT_HANDLE_INFORMATION ObjectHandleInfo; #025 PAGED_CODE ; #026 CapturedByteOff .QuadPart = 0; #027 IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle); #028 获取文件对象 ![](/icons/96537dou2.gif) #029 /* Get File Object */ #030 Status = ObReferenceObjectByHandle(FileHandle, #031 0, #032 IoFileObjectType, #033 PreviousMode, #034 (PVOID*)&FileObject, #035 &ObjectHandleInfo); #036 (!NT_SUCCESS(Status)) Status; #037 检查是否用户模式 ![](/icons/96537diaoyong.gif) ![](/icons/96537dou.gif) 如果是就需要使用SEH机制
#038 /* Validate User-Mode Buffers */ #039 (PreviousMode != KernelMode) #040 { #041 _SEH2_TRY #042 { 检查是否有写文件 ![](/icons/96537de.gif) 权限 ![](/icons/96537dou2.gif) #043 /* #044 * Check the handle has either FILE_WRITE_DATA or #045 * FILE_APPEND_DATA granted. However, this is a named pipe, #046 * make sure we don't ask for FILE_APPEND_DATA as it erferes #047 * with the FILE_CREATE_PIPE_INSTANCE access right! #048 */ #049 (!(ObjectHandleInfo.GrantedAccess & #050 ((!(FileObject->Flags & FO_NAMED_PIPE) ? #051 FILE_APPEND_DATA : 0) | FILE_WRITE_DATA))) #052 { #053 /* We failed */ #054 ObDereferenceObject(FileObject); #055 _SEH2_YIELD( STATUS_ACCESS_DENIED); #056 } #057 获取状态代码块 ![](/icons/96537dou2.gif) #058 /* Probe the status block */ #059 ProbeForWriteIoStatusBlock(IoStatusBlock); #060 #061 /* Probe the read buffer */ #062 ProbeForRead(Buffer, Length, 1); #063 #064 /* Check we got a off */ #065 (ByteOff ) #066 { #067 /* Capture and probe it */ #068 CapturedByteOff = ProbeForReadLargeInteger(ByteOff ); #069 } #070 #071 /* Capture and probe the key */ #072 (Key) CapturedKey = ProbeForReadUlong(Key); #073 } #074 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) #075 { #076 /* Get the exception code */ #077 Status = _SEH2_GetExceptionCode ; #078 } #079 _SEH2_END; #080 #081 /* Check for probe failure */ #082 (!NT_SUCCESS(Status)) Status; #083 } #084 ![](/icons/96537else.gif) #085 { #086 /* Kernel mode: capture directly */ #087 (ByteOff ) CapturedByteOff = *ByteOff ; #088 (Key) CapturedKey = *Key; #089 } #090
相关文章
读者评论
发表评论
|
|