专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »编程综合 » reactos:reactos操作系统实现(88) »正文

reactos:reactos操作系统实现(88)

来源: 发布时间:星期一, 2009年9月28日 浏览:0次 评论:0
  IRP 是 I/O request packet 缩写即 I/O 请求包驱动和驱动的间通过 IRP 进行通信而使用驱动应用层 CreatFile,ReadFile,WriteFile,DeviceIoControl 等说到底也是使用 IRP 和驱动进行通信

  个 IRP 由两部分组成首先是头部或者叫包固定部分个 IRP 结构紧跟在这个头部的后是 I/O栈位置这是个 IO_STACK_LOCATION 结构这个中元素个数是根据情况而定由 IoAllocateIrp( IN CCHAR StackSize , IN BOOLEAN ChargeQuota ) 时参数 StackSize 决定而 StackSize 通常由 IRP 发往目标 DEVICE_OBJECT StackSize 决定而这个 StackSize 是由设备对象连入所在设备栈时根据在设备栈中位置决定我们先看看 IRP 结构和 IO_STACK_LOCATION 结构定义实现代码如下:

#001  typedef struct _IRP {

  标志IRP类型

#002       CSHORT  Type;

  本IRP长度和IRP栈长度

#003       USHORT  Size;

  指向内存描述符列表

#004       struct _MDL  *MdlAddress;

  IRP包特征标志比如直接I/O还是缓存CacheI/O等等

#005       ULONG  Flags;

  保存驱动相关数据结构其中和WDM驱动相关指针是AssociatedIrp.Buffer Buffer指针指向个数据缓冲区该缓冲区位于内核模式非分页内存中对于IRP_MJ_READ和IRP_MJ_WRITE操作如果顶级设备指定DO_BUFFERED_IO标志则I/O管理器就创建这个数据缓冲区对于IRP_MJ_DEVICE_CONTROL操作如果I/O控制功能代码指出需要缓冲区(见第 9章)则I/O管理器就创建这个数据缓冲区I/O管理器把用户模式发送给驱动数据复制到这个缓冲区这也是创建IRP过程部分这些数据可以是和WriteFile有关数据或者是DeviceIoControl中所谓输入数据对于读请求设备驱动把读出数据填到这个缓冲区然后I/O管理器再把缓冲区内容复制到用户模式缓冲区对于指定了METHOD_BUFFEREDI/O控制操作驱动把所谓输出数据放到这个缓冲区然后I/O管理器再把数据复制到用户模式输出缓冲区

#006       union {
#007              struct _IRP  *MasterIrp;
#008              volatile LONG  IrpCount;
#009              PVOID  Buffer;
#010       } AssociatedIrp;


  当前线程入口

#011       LIST_ENTRY  ThreadListEntry;

  个仅包含两个域结构驱动在最终完成请求时设置这个结构

#012       IO_STATUS_BLOCK  IoStatus;

  等于个枚举常量UserMode或KernelMode指定原始I/O请求来源驱动有时需要查看这个值来决定是否要信任某些参数

#013       KPROCESSOR_MODE  RequestorMode;

  IRP是否被阻塞

#014       BOOLEAN  PendingReturned;

  IRP栈大小

#015       CHAR  StackCount;

  当前栈位置

#016       CHAR  CurrentLocation;

  IRP是否被取消操作

#017       BOOLEAN  Cancel;

  当IoAcquireCancelSpinLock指明它是那个IRQ级别

#018       KIRQL  CancelIrql;

  APC环境索引

#019       CCHAR  ApcEnvironment;

  内存分配方式比如定额地增加还是固定大小等等

#020       UCHAR  AllocationFlags;

  保存用户I/O状态

#021       PIO_STATUS_BLOCK  UserIosb;

  保存用户事件

#022       PKEVENT  UserEvent;

  APC、或分配内存大小

#023       union {
#024              struct {
#025                     PIO_APC_ROUTINE  UserApcRoutine;
#026                     PVOID  UserApcContext;
#027              } AsynchronousParameters;
#028              LARGE_INTEGER  AllocationSize;
#029       } Overlay;


  驱动取消例程地址

#030       volatile PDRIVER_CANCEL  CancelRoutine;

  指向用户缓冲区

#031       PVOID  UserBuffer;
 
 
#032       union {


  设备队列入口或者设备上下环境指针

#033              struct {
#034                     _ANONYMOUS_UNION union {
#035                            KDEVICE_QUEUE_ENTRY  DeviceQueueEntry;
#036                            _ANONYMOUS_STRUCT struct {
#037                                   PVOID  DriverContext[4];
#038                            } DUMMYSTRUCTNAME;
#039                     } DUMMYUNIONNAME;


  批向内核线程

#040                     PETHREAD  Thread;

  辅助缓冲区

#041                     PCHAR  AuxiliaryBuffer;

  I/O栈位置

#042                     _ANONYMOUS_STRUCT struct {
#043                            LIST_ENTRY  ListEntry;
#044                            _ANONYMOUS_UNION union {
#045                                   struct _IO_STACK_LOCATION  *CurrentStackLocation;
#046                                   ULONG  PacketType;
#047                            } DUMMYUNIONNAME;
#048                     } DUMMYSTRUCTNAME;


  原来文件对象

#049                     struct _FILE_OBJECT  *OriginalFileObject;
#050              } Overlay;


  APC队列

#051              KAPC  Apc;

  I/O完成设置用户关键数据

#052              PVOID  CompletionKey;
#053       } Tail;
#054  } IRP;
#055  typedef struct _IRP *PIRP;


  上面学习了IRP结构知道了IRP保存基本内容也就是说知道了有什么相关东西这就相当有了原材料那么如何样加工和处理这些原材料呢?那就得去分析IRP相关操作也就是IRP相关算法下面就从IRP分配开始实现代码如下:

#001  PIRP
#002  NTAPI
#003  IoAllocateIrp(IN CCHAR StackSize,
#004                IN BOOLEAN ChargeQuota)
#005  {
#006      PIRP Irp = NULL;


  计算IRP占用大小包括IRP头部和IRP栈空间

#007      USHORT Size = IoSizeOfIrp(StackSize);
#008      PKPRCB Prcb;
#009      UCHAR Flags = 0;
#010      PNPAGED_LOOKASIDE_LIST List = NULL;
#011      PP_NPAGED_LOOKASIDE_NUMBER ListType = LookasideSmallIrpList;
#012


  如果设置为定额分配方式就添加这个标志位

#013      /* Set Charge Quota Flag */
#014       (ChargeQuota) Flags |= IRP_QUOTA_CHARGED;
#015 
#016      /* FIXME: Implement Lookaside Floats */
#017     
#018      /* Figure out which Lookaside List to use */
#019       ((StackSize <= 8) && (ChargeQuota  FALSE))
#020      {


  设置为固定分配大小空间

#021          /* Set Fixed Size Flag */
#022          Flags = IRP_ALLOCATED_FIXED_SIZE;
#023 


  需要使用个大列表方式

#024          /* See  we should use big list */
#025           (StackSize != 1)
#026          {
#027              Size = IoSizeOfIrp(8);
#028              ListType = LookasideLargeIrpList;
#029          }
#030 


  获取当前处理器控制块

#031          /* Get the PRCB */
#032          Prcb = KeGetCurrentPrcb;
#033 


  获取后备列表

#034          /* Get the P List First */
#035          List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[ListType].P;
#036 


  从后备列表里分配个IRP包

#037          /* Attempt allocation */
#038          List->L.TotalAllocates;
#039          Irp = (PIRP)InterlockedPopEntrySList(&List->L.ListHead);
#040 
#041          /* Check  the P List failed */
#042           (!Irp)
#043          {
#044              /* Let the balancer know */
#045              List->L.AllocateMisses;
#046 
#047              /* Try the L List */
#048              List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[ListType].L;
#049              List->L.TotalAllocates;
#050              Irp = (PIRP)InterlockedPopEntrySList(&List->L.ListHead);
#051          }
#052      }
#053 


  如果没有从后备列表里分配到IRP就需要从内存里分配

#054      /* Check  we have to use the pool */
#055       (!Irp)
#056      {


  从后备列表里分配失败

#057          /* Did we try lookaside and fail? */
#058           (Flags & IRP_ALLOCATED_FIXED_SIZE) List->L.AllocateMisses;
#059 


  定额增加分配方式

#060          /* Check  we should charge quota */
#061           (ChargeQuota)
#062          {
#063              /* Irp = ExAllocatePoolWithQuotaTag(NonPagedPool, Size, TAG_IRP); */
#064              /* FIXME */
#065              Irp = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_IRP);
#066          }
#067          
#068          {


  非定额增加分配方式

#069              /* Allocate the IRP With no Quota charge */
#070              Irp = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_IRP);
#071          }
#072 
#073          /* Make sure it was sucessful */
#074           (!Irp) (NULL);
#075      }
#076      
#077      {
#078          /* In this  there is no charge quota */
#079          Flags &= ~IRP_QUOTA_CHARGED;
#080      }
#081




  现在化IRP些属性

#082      /* Now Initialize it */
#083      IoInitializeIrp(Irp, Size, StackSize);
#084 


  设置IRP分配标志

#085      /* Set the Allocation Flags */
#086      Irp->AllocationFlags = Flags;
#087 


  返回分配成功IRP包

#088      /* Return it */
#089      IOTRACE(IO_IRP_DEBUG,
#090              "%s - Allocated IRP %p with allocation flags %lx\n",
#091              __FUNCTION__,
#092              Irp,
#093              Flags);
#094       Irp;
#095  }




标签:reactos
0

相关文章

读者评论

发表评论

  • 昵称:
  • 内容: