windows驱动学习_Second

来源:互联网 发布:网络银行办理 编辑:程序博客网 时间:2024/06/05 05:14

windows驱动学习_Second

一.内核空间和用户空间

1.在单个进程内的编程特点:

  (1)可以自由使用通用寄存器,不用关心这些寄存器被其他进程修改。不同进程看似各自拥有一套通用寄存器。

  (2)原则上可以自由使用0-N范围内的内存空间,N的大小取决于操作系统的位数,每个进程的用户空间内存是隔离的。

  (3)通过操作系统约定的方式与其他进程共享其他资源。

    因此,在单个进程内编程只需要定义和使用本进程所需要的资源,并编写代码操作这些资源,不需要关心其他进程。

2.进程的空间实际上被分成两部分。一部分供进程独立使用,称为用户空间;另一部分容纳操作系统的内核,称为内核空间或称为系统空间

3.用户空间是各个进程隔离的,但是内核空间是共享的。  

4.内核空间是收到硬件保护的,比如x86架构下R0层(Ring 0)的代码才可以访问内核空间,普通应用程序编译出来之后都运行的R3层,R3层的代码要调用R0层的功能时,一般通过操作系统提供的一个入口来实现。这样应用程序既可以调用操作系统内核中提供的功能,又不至于得到随意修改内核的权利。

5.内核模块位于内核空间,而内核空间又被所有的进程共享。因此内核模块实际上是位于任何一个进程空间中。但是任意一段代码的任意一次执行,一定是位于某个进程空间中的。这个进程是哪个可以通过PsGetCurrentProcessId函数能获得当前进程的进程号。

 

二.数据类型

 1.使用宏NT_SUCCESS()可以判断一个返回值是否成功,如果成功,毫无疑问返回STATUS_SUCESS。(返回值定义存在ntstatus.h中)。

 2.UNICODE_STRING是宽字符,双字节的,可直接用DbgPrint打印,用%wZ。

 

三.重要的数据结构

1.驱动对象

typedef struct _DRIVER_OBJECT {    CSHORT Type;    CSHORT Size;    //    // The following links all of the devices created by a single driver    // together on a list, and the Flags word provides an extensible flag    // location for driver objects.    //    PDEVICE_OBJECT DeviceObject;    ULONG Flags;    //    // The following section describes where the driver is loaded.  The count    // field is used to count the number of times the driver has had its    // registered reinitialization routine invoked.    //    PVOID DriverStart;    ULONG DriverSize;    PVOID DriverSection;    PDRIVER_EXTENSION DriverExtension;    //    // The driver name field is used by the error log thread    // determine the name of the driver that an I/O request is/was bound.    //    UNICODE_STRING DriverName;    //    // The following section is for registry support.  Thise is a pointer    // to the path to the hardware information in the registry    //    PUNICODE_STRING HardwareDatabase;    //    // The following section contains the optional pointer to an array of    // alternate entry points to a driver for "fast I/O" support.  Fast I/O    // is performed by invoking the driver routine directly with separate    // parameters, rather than using the standard IRP call mechanism.  Note    // that these functions may only be used for synchronous I/O, and when    // the file is cached.    //    PFAST_IO_DISPATCH FastIoDispatch;    //    // The following section describes the entry points to this particular    // driver.  Note that the major function dispatch table must be the last    // field in the object so that it remains extensible.    //    PDRIVER_INITIALIZE DriverInit;    PDRIVER_STARTIO DriverStartIo;    PDRIVER_UNLOAD DriverUnload;    PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1];} DRIVER_OBJECT;typedef struct _DRIVER_OBJECT *PDRIVER_OBJECT; 

   和编写一个应用程序,windows直接从main()函数开始执行来生成一个进程不同,内核模块并不生成一个进程,只写一组回调函数让windows来调用,而且这组回调函数必须符合windows内核规定。如上述结构体中,这一组回调函数包括“普通分发函数” MajorFunction和“快速分发函数” FastIoDispatch,这些函数用来处理和发送给这个内核模块的请求。

2.设备对象

typedef struct DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) _DEVICE_OBJECT {    CSHORT Type;    USHORT Size;    LONG ReferenceCount;    struct _DRIVER_OBJECT *DriverObject;    struct _DEVICE_OBJECT *NextDevice;    struct _DEVICE_OBJECT *AttachedDevice;    struct _IRP *CurrentIrp;    PIO_TIMER Timer;    ULONG Flags;                                // See above:  DO_...    ULONG Characteristics;                      // See ntioapi:  FILE_...    __volatile PVPB Vpb;    PVOID DeviceExtension;    DEVICE_TYPE DeviceType;    CCHAR StackSize;    union {        LIST_ENTRY ListEntry;        WAIT_CONTEXT_BLOCK Wcb;    } Queue;    ULONG AlignmentRequirement;    KDEVICE_QUEUE DeviceQueue;    KDPC Dpc;    //    //  The following field is for exclusive use by the filesystem to keep    //  track of the number of Fsp threads currently using the device    //    ULONG ActiveThreadCount;    PSECURITY_DESCRIPTOR SecurityDescriptor;    KEVENT DeviceLock;    USHORT SectorSize;    USHORT Spare1;    struct _DEVOBJ_EXTENSION  *DeviceObjectExtension;    PVOID  Reserved;} DEVICE_OBJECT;

在内核世界里,大部分“消息”都以请求IRP的方式传递,而设备对象是唯一可以接受请求的实体,任何一个请求都是发送给某个设备对象的。

四.请求

     大部分请求以IRP的形式发送,IRP是一个内核数据结构,这个结构表示无数种实际请求。一个IRP往往要传递n个设备才能得以完成,在传递过程中,有可能会有一些“中间变换”,导致请求的参数变化,为了保存这种参数变化,给每次“中转”都留一个“栈空间”,用来保存中间参数。

五.函数

     内核中printf、scanf及fopen、fclose、fwrite、fread、malloc、free、strdup这些函数无法使用,因为在内核没有控制台,而且读\写文件也不那么轻松。但是sprintf、strlen、strcpy、wcslen、wcscpy、memcpy、memset都是可以的。

六.代码的中断级

      Passive级和Dispatch级

七.特殊代码

      #pragma alloc_text  用来指定某个函数的可执行代码在编译出来后再sys文件中的位置;INIT节的特点是在初始化完毕后就被释放,不再占用内存空间;PAGE节的特点是位于可以进行分页交换的内存空间,这些空间在内存紧张时可以被交换到硬盘上已节省内存;PAGELK节加载后位于不可分页交换的内存空间。(放在PAGE节的函数不可以在Dispatch级调用,因为这种函数调用可能诱发缺页中断,但是缺页中断处理不能再Dispatch级完成,一般用PAGED_CODE()进行测试,如果发现当前中断级为Dispatch级,则程序直接报异常)

 


 

 

 

0 0
原创粉丝点击