Windows驱动开发技术详解 笔记1

来源:互联网 发布:韩国大学知乎 编辑:程序博客网 时间:2024/05/17 21:47

1.Windows驱动程序分为两类:NT式驱动程序,WDM式驱动程序。
2.驱动程序的入口函数DriverEntry,它有两个参数DriverObject 和RegistryPath。
    DriverEntry函数由IO管理器负责调度,这两个函数也是由IO管理器负责分配和指定的。第一个代表IO管理器传递进来的驱动程序对象,第二个指向此驱动程序负责的注册表。
3.设备类型FILE_DEVICE_UNKNOWN此种设备为独占设备,即设备只能被一个应用程序所使用。
4.设备对内存的操作有两种方式:DO_BUFFERED_IO和 DO_DIRECT_IO
5.驱动卸载例程
    VOID DriverUnload (IN PDRIVER_OBJECT pDriverObject)
    {
        PDEVICE_OBJECT    pNextObj;
        pNextObj = pDriverObject->DeviceObject;
       //遍历设备对象链表,删除设备
       while (pNextObj != NULL)
       {
            PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pNextObj->DeviceExtension;
            //删除符号链接
            UNICODE_STRING pLinkName = pDevExt->ustrSymLinkName;
            IoDeleteSymbolicLink(&pLinkName);
            pNextObj = pNextObj->NextDevice;
            IoDeleteDevice( pDevExt->pDevice );
        }
     }
6.在VS2005中配置驱动开发环境参考:http://blog.sina.com.cn/s/blog_5371d2790100bsy2.html
  在visual c++ 6.0 中配置驱动开发环境参考《windows驱动程序开发技术详解》--1.3.2节
7.NT或WDM式的驱动程序在默认情况下是隐藏的,但也可以通过设备管理器来查看,路径如下:
  设备管理器--->查看---->显示隐藏的设备----->非即插即用设备
8.有些代码中会看到这样的字段,比如:
  #pragma INITCODE
  NTSTATUS DriverEntry().........
  其中的#pragma 指明函数是加载到INIT内存区域中的。INIT标志指明该函数只是在加载的时候需要装入内存,当程序被卸载以后,该函数可以从内存区域中卸载掉。

  可以通过以下方式定义分页内存,非分页内存,初始化内存等:
   #define PAGEDCODE code_seg("PAGE")//分页内存
   #define LOCKEDCODE code_seg()     //非分页内存
   #define INITCODE code_seg("INIT")//初始化内存
   #define PAGEDDATA data_seg("PAGE")//分页内存
   #define LOCKEDDATA data_seg()     //非分页内存
   #define INITDATA data_seg("INIT")//初始化内存

8.WDM驱动程序中有一个dispatch 例程:AddDevice,该dispatch routine是用来创建设备对象并由PNP管理器调用的。
    DriverObject->DriverExtension->AddDevice = DriverAddDeviceRoutine;
9.俄从去年就开始研究WDM驱动程序,到现在才发现俺写的一直都是NT式的驱动程序。唉..........
10.WDM和NT式驱动的一个重要区别就是要对IRP_MJ_PNP请求进行处理。还有一个就是AddDevice例程。
11.PAGED_CODE()
   这是一个DDK提供的宏,只在check版中有效。当此例程所在的中断请求级别超过APC_LEVEL时,会产生一个断言,断言会使程序终止,并报告出错的地址。
12.WDM 驱动程序的加载
   WDM驱动程序不能像NT式驱动程序一样以服务的形式加载到系统中,需要自己编写一个inf文件,可以使用由DriverStufio自带的EzDriverInstaller工具。
   还可以才用如下的方式:
   控制面板--->添加硬件--->"是,我已经连接了此硬件"--->“添加新的硬件设备”--->“安装我手动从列表中选择的硬件(高级)”--->显示所有设备--->从磁盘安装。
   这种方式比较繁琐,而且需要等待系统枚举所有的设备,可能要等很长时间,所以还是推荐使用EzDriverInstaller安装、启动、关闭、卸载、重启。
13.科普知识
   Windows 9X系列:Windows95、Windows98、Windows ME
   Windows NT系列:Windows NT3.1(93年7)、Windows NT3.5(94年9)、Windows NT4.0(96年7)
                   Windows 2000(99年12)、Windows XP(01年8)、Windows Server 2003(03年3)

14.Windows驱动程序和普通win32的应用程序一样,也是PE格式的文件。C语言中对变量的声明必须在函数的首部,而C++则没有这个限制。但是C++的许多高级特性是不适合用来开发驱动程序的,所以可以使用C++的简单特性来写驱动程序。但最好还是用C。

15.当一个函数被调用的时候,首先压入函数的各个参数,然后压入函数的返回地址。当函数退出的时候以相反的顺序依次退出堆栈,从而保持了堆栈的平衡。

   C语言调用约定:(__cdecl)从右到左参数入栈,调用者恢复堆栈。

   标准调用约定:(__stdcall)从右向左参数入栈,函数本身负责恢复堆栈

   Windows驱动程序的编译需要使用标准调用约定,尤其是入口函数。所以用VC编译器的时候应该将VC的C语言调用约定更改为标准调用约定。(Vs2005中我没有更改,编写的驱动也是照样可以运行,所以此说法有待验证。)如果用DDK编译则可以忽略这个环节。

16.在C++中添加C语言的程序,需要用extern "C"来修饰

   有时候 出现下面的错误,可以考虑在代码前面加上以上修饰符。

   :error LNK2001:unresolved external symbol "unsigned long __cdecl 。。。。"

17.Windows操作系统规定,在内核模式的程序无法调用用户模式的程序,而用户模式的程序可以调用内核态的程序。

18.WDM驱动程序加载

   (1)Windows在安装的时候会提供很多INF文件,根据不同的VernderID何ProductID,会找出合适这个设备的INF文件,如果系统中没有合适的INF文件,系统会向用户询问是否可以提供这个INF文件,如果不能则尝试到微软网站去寻找。找到INF文件后,系统会根据INF文件上的指示,将驱动程序(.sys文件)和相关文件复制到系统指定目录下,并且修改注册表。同时通知PNP管理器和I/O管理器,创建新设备,并运行驱动程序的入口程序DriverEntry。

   (2)INF文件剖析:INF文件是一个文本文件,由若干个节(Section)组成。每个节的名称用一个方括号指示,紧接着方括号后面的就是节的内容。每一行就是一项内容,其形式都是类似SomeEntry = SomeValue。每个项的顺序是可以颠倒的,但系统分析INF文件的时候,是顺序解析的。INF中注释语句是用分号开头的。

原创粉丝点击