chapter 2.5: 内核模式编程基础

来源:互联网 发布:mac无法播放网页视频 编辑:程序博客网 时间:2024/06/06 03:58
要特别注意page fault,会引起系统崩溃。

中断和IRQL
中断:对应于每个硬件事件。软件也可以生成软件中断(DPC),可以用来处理硬件中断。
    windows把中断传给处理器。
    windows对已有线程进行中断来处理中断。
IRQL:所有中断都对应着中断级别,越高越优先。
    **注意中断优先级和线程优先级的不同
    PASSIVE_LEVEL:
        最低的IRQL,正常线程的默认运行级别,不能产生中断,可以调用所有windows核心服务。
    DISPATCH_LEVEL:
        软件中断中的最高级别中断,可以调用有限的windows核心服务。
    DIRQL:
        驱动级别的中断,device-IRQLs,可以调用一些windows核心服务。
    **要选择正确的中断级别,Driver Verifier和SDV可以用来协助解决这些错误。

并行和同步
线程和同步在驱动级别的机制和应用级别不同。
线程:
    驱动不会创建线程或者在某一个具体的线程上运行。
驱动例程不会知道具体在哪个进程的哪个线程中运行。
    系统只是借用已有的线程来执行驱动例程。
    线程的借用:
        1.应用程序在线程A中调用DeviceIoControl来向驱动发起请求。
        2.I/O manager在线程A中调用dispatch routine
        3.驱动处理请求,返回线程的控制权给应用程序
        4.设备处理完请求后,产生硬件中断,选择一个arbitrary thread context由ISR处理,具体的线程无法由驱动决定。
        5.ISR产生一个DPC进入队列,在一个更低级别的IRQL中选择一个arbitrary thread context处理DPC。
    arbitrary thread context的实现:
        1.选择不同的例程和不同的线程。
        2.例程和线程停止,借给操作系统让更低级别IRQL运行。
同步:
    用来防止race conditions
    内核模式的同步和用户模式不同。
PASSIVE_LEVEL的同步
    1.使用Kernel dispatcher objects
        objects-event,semaphore,mutex
    2.Fast mutex和resource objects
High-IRQL同步
    spin lock:
        当一个线程拥有spin lock时,其他要获取spin lock的线程等待。
        可以在DISPATCH_LEVEL及below使用spin lock
        创建对象时,可以使用spin lock对象保护该对象,并保存spin lock备用。
        使用spin lock时IRQL必须升到DISPATCH_LEVEL
    interrupt spin lock:
        ISR需要对相关的DPC或其他ISRs同步
        DIRQL中不能用spin lock,只能用interrupt spin lock
        用法和spin lock一样
        使用interrupt spin lock时IRQL必须升到DIRQL
Race Conditions和Dead locks
    防止的两种方法:同步(使用同步对象)和序列化(序列化请求)
    在free build更容易产生race condition


内核区域的内存
用户模式类似:都使用虚拟地址空间
用户模式区别:
    所有内核模式驱动共享一个虚拟地址空间
    用户模式进程不能访问内核模式空间
    内核模式进程可以访问用户模式地址空间
内核进程访问用户空间需要一个安全的访问方法保证有效性:
    驱动可以探测和锁定用户模式里的缓存。
内存管理
    共同点:都要分配和释放内存,使用栈,处理faults
    不同点,page faults 问题:
        IRQL>=DISPATCH_LEVEL:page fault会产生bug check(IRQL_NOT_LESS_OR_EQUAL),可以使用PREfast和SDV差错
        IRQL<DISPATCH_LEVEL:page fault只会产生延迟,但是会产生deadlock和double-fault crash
内存池:
    驱动必须使用的内存池分配内存。
    1.Paged pool:可以被paged out,用来存储<DISPATCH_LEVEL相关的数据。
    2.Nonpaged pool:不能被paged out,空间有限,用来存储>=DISPATCH_LEVEL相关的数据。
kernel stack
    很小而且不会增加,需要小心使用:
        1.递归例程最好别使用kernel stack
        2.disk I/O path对kernel stack使用很敏感
        3.不要把大量数据放入stack,而是指针。
4.怎样不使用kernel stack:http://go.microsoft.com/fwlink/?LinkId=79604
MDLs
    内核数据缓冲经常会以MDL方式使用,包括buffer和组成buffer的locked pages的列表
原创粉丝点击