windows驱动学习_Second

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值