第 10 章 PC 机的高级编程技术

82
1 微微微微微微 10 微 PC 微微微微微微微微

description

第 10 章 PC 机的高级编程技术. 10.1 PC 机环境下软件对接口的访问层次. 应用程序. 操作系统 驱动程序. 间接访问. BIOS. 直接访问. 裸机. 1. 直接访问层次. 特点 :可以直接进行内存和端口的访问,也可以自行决定是否在实模式和保护模式间切换。通常所有的端口和内存都是对程序员开放的。 工具 :汇编语言或 C 语言。 应用 : BIOS 都是基于这种低级层次用汇编来编写的。驱动程序也有使用这种方法的。 优点 :能够编写速度最快,占用空间最小的有效代码。 缺点 :需要对硬件和接口有很熟悉的了解。 - PowerPoint PPT Presentation

Transcript of 第 10 章 PC 机的高级编程技术

Page 1: 第 10 章   PC 机的高级编程技术

1

微计算机系统

第 10 章 PC 机的高级编程技术

Page 2: 第 10 章   PC 机的高级编程技术

2

微计算机系统10.1 PC 机环境下软件对接口的访问层次

裸机BIOS 直接访问直接访问

操作系统驱动程序驱动程序间接访问间接访问应用程序

Page 3: 第 10 章   PC 机的高级编程技术

3

微计算机系统1. 直接访问层次特点特点:可以直接进行内存和端口的访问,也可以自行决定是否在实模式和保护模式间切换。通常所有的端口和内存都是对程序员开放的。工具工具:汇编语言或 C 语言。应用应用: BIOS 都是基于这种低级层次用汇编来编写的。驱动程序也有使用这种方法的。优点优点:能够编写速度最快,占用空间最小的有效代码。缺点缺点:需要对硬件和接口有很熟悉的了解。 要会汇编,或熟练使用 C 语言的指针。 不利于增加对新设备的控制。

Page 4: 第 10 章   PC 机的高级编程技术

4

微计算机系统2.BIOS 访问层次特点特点:通过 BIOS 提供的功能调用间接地对内存或端口访问,从而控制硬件。工具工具:汇编语言或 C 语言。应用应用:驱动程序有些会使用这些功能调用。需要获得高效率的应用程序也采用这种方法。优点优点:能够编写速度较快的有效代码。 可以不需要编写直接对硬件进行控制的代码。缺点缺点:需要对底层信号有所了解。 增加对新设备的控制不是很方便,但好于低级层次。

Page 5: 第 10 章   PC 机的高级编程技术

5

微计算机系统3. 驱动程序层次特点特点:使用 BIOS 功能调用和直接内存访问的方法编写符合特定操作系统管理规范的设备驱动程序。工具工具: VC++ 与 DDK 开发包,或第三方开发工具如 DriverStudio 。应用应用:在操作系统层面上的设备控制,并为应用程序提供 API 支持。优点优点:既控制硬件,又保证操作系统的完整与安全。缺点缺点:需要对底层信号有所了解。 需要对操作系统的各个管理模块有深入的了解。

Page 6: 第 10 章   PC 机的高级编程技术

6

微计算机系统4. 应用层次特点特点:使用操作系统各种驱动程序所提供的功能调用或 API 函数间接对硬件或内存进行访问。工具工具: VC++ 、 Delphi 、 Java 等。应用应用:编写面向终端用户的各类应用程序。优点优点:无需对硬件控制有太多了解,只需完成应用层面的工作就可以 ,而且还保证操作系统的完整与安全。缺点缺点:需要了解大量的 API 和功能调用函数的功能。 由于是间接调用,所以代码的效率和编译系统有很大的关系。

Page 7: 第 10 章   PC 机的高级编程技术

7

微计算机系统

16 位段地址 16 位段内偏移:

16 位段地址16 位段内偏移

(左移四位)+

20 位物理地址=

6417H 0100H ∶6417H×10H + 0100H = 64170H + 0100H = 64270H

采用了内存分段的办法,内存分为若干段,段的大小根据需要决定,最大为 64KB

10.2.1 实地址模式的存储管理(同 PC/XT )10.2 Pentium 4 的内存管理——接口直接访问

Page 8: 第 10 章   PC 机的高级编程技术

8

微计算机系统000000

0A0000

100000110000

≈≈FFFFFF

640KB 常规内存384KB 高端内存64KB 高内存区

1~4095MB扩展内存

存放用户程序和存放用户程序和 DDOSOS 驻留部分驻留部分存放显存、网卡和部分存放显存、网卡和部分用户的用户的 DOSDOS 驱动程序和驱动程序和BIOSBIOS存放部分存放部分 DOSDOS 驻留程序驻留程序大于大于 1M1M 以上的 扩展内以上的 扩展内存,存, DOSDOS 下不能直接访下不能直接访问,需要用问,需要用 XMSXMS 规范规范使用。可利用使用。可利用 DOSDOS 调用调用或或 BIOSBIOS 调用来使用。调用来使用。

Page 9: 第 10 章   PC 机的高级编程技术

9

微计算机系统10.2.2 保护模式下使用的系统地址寄存器 • GDTR — 48GDTR — 48 位的全局描述符表寄存器 位的全局描述符表寄存器

全局描述符表 32 位线性地址 16 位界限值 • IDTR — 48IDTR — 48 位的中断描述符表寄存器 位的中断描述符表寄存器 中断描述符表 32 位线性地址 16 位界限值 • TR — 16TR — 16 位的任务状态段寄存器 位的任务状态段寄存器

TSS 的 16 位选择字 • LDTR — 16LDTR — 16 位的局部描述符选择字寄存器 位的局部描述符选择字寄存器

LDT 的 16 位选择字

Page 10: 第 10 章   PC 机的高级编程技术

10

微计算机系统10.2.3 保护模式下 Pentium 4 的段式存储管理 1. 段式管理的地址变换

段寄存器的 15~2位 偏移量45 32 31 0

段描述符 段表32 位线性地址 物理地址

逻辑地址段基址

Pentium Pentium 系列的虚拟地址空间是系列的虚拟地址空间是 224646 == 64TB64TB 。。

Page 11: 第 10 章   PC 机的高级编程技术

11

微计算机系统2. 段描述符

D7 D0段界限 7~0段界限 15~8基址 7~0

基址 15~8

基址 23~16

基址 31~24

TYPESAVL

DPLPG D/B 0 段界限 19~16

01234

567

Page 12: 第 10 章   PC 机的高级编程技术

12

微计算机系统D7 D0

AVLG D/B 0 段界限 19~16

用户的操作系统可用位

D/B 位代码段 (D 位 )

D=1 使用 32 位操作系统和 32 位寻址方式D=0 使用 16 位操作系统和 16 位寻址方式

数据段 (B 位 )B=1 使用 ESP 寄存器,上限为 FFFFFFFFH B=0 使用 SP 寄存器,上限为 FFFFH

G=0 段长以 1 字节为单位G=1 段长以 4K 字节为单位

D/B 位粒度位

Page 13: 第 10 章   PC 机的高级编程技术

13

微计算机系统

AWR

EDC

E=0E=1S=1DPLP

D7 D0

存在位 特权位S=1 是非系统段S=0 是系统描述符

代码段标志

数据段标志

兼容位可读位

访问位

扩展方向位 可写位

非系统段中的第 5 字节

可执行位

Page 14: 第 10 章   PC 机的高级编程技术

14

微计算机系统系统描述符中的 TYPE

Page 15: 第 10 章   PC 机的高级编程技术

15

微计算机系统

RPLTi

选择符(段寄存器)15 2 1 0索引

Ti=1Ti=0

……

01

……

01

LDT

LDT

LDT

GDT

基址界限选择符基址界限

LDTR GDTR

22

Page 16: 第 10 章   PC 机的高级编程技术

16

微计算机系统#include "stdafx.h"#include <stdio.h>#include <wtypes.h> // wtypes.h// wtypes.h 定义了定义了 WORDLONG, WORDLONG,

//DWORD,WORD//DWORD,WORD 等数据类型等数据类型DWORDLONG gdtr,savegdt;//// 下面是下面是 GDTGDT 中将创建的数据段描述符表中将创建的数据段描述符表 ,, 基地址基地址 0X00000F000X00000F00,,//// 段界限为段界限为 0XFFFF,0XFFFF, 优先级为优先级为 33 的在内存中的可写数据段的在内存中的可写数据段WORD descriptor[4]= {0xFFFF, 0X0F00, 0XF200,

0X0040}; int result[10];int main ( int argc, char* argv[] ){_asm { push ebp

sgdt gdtr // // 将将 GDTRGDTR 寄存器的内容读取到寄存器的内容读取到////gdtrgdtr 开始的开始的 66 个字节中,其中个字节中,其中// // 前两个字节给出前两个字节给出 GDTGDT 的界限值的界限值 ,,//// 高高 44 个字节给出个字节给出 GDTGDT 的基地址的基地址

Page 17: 第 10 章   PC 机的高级编程技术

17

微计算机系统mov ebp,dword ptr [gdtr+2] // // 将将 gdtgdt 的基的基

// // 地址读到地址读到 EBPEBP 中中add ebp,70h // // 我们选择我们选择 70H70H 偏移下的段描述偏移下的段描述

// // 符(符( GDTGDT 中第中第 1414 个描述符)个描述符)lea edi,savegdtmov esi,ebpmovsd /// / 以上以上 44条指令保存原来在条指令保存原来在 70H70H 偏移上偏移上movsd // // 的描述符的描述符mov edi,ebplea esi,descriptor;movsd // // 把我们的数据段描述符装入把我们的数据段描述符装入 70H70Hmovsd // // 偏移上偏移上push esmov ax,0073h /// / 选择字为描述符偏移选择字为描述符偏移 70H70H 拼接上拼接上

// // 低低 33 位控制位元位控制位元 ,, 其中其中 TiTi 为为 0,0, 表表// // 示访问示访问 GDT,RPLGDT,RPL 为为 11,11, 为为 33 级优级优// // 先级先级 ,, 所以就为所以就为 73H73H

Page 18: 第 10 章   PC 机的高级编程技术

18

微计算机系统mov es,ax // ES// ES 装入选择字装入选择字 73H73Hlea edi,result /// / 将存放输出结果的变量将存放输出结果的变量

//// 的地址放在的地址放在 EDIEDI 中中mov eax,1mov ebx,1

}_asm{ mov cx,10a1 : mov es : [eax],eax

add eax,4loop a1 // // 上面上面 44条指令将向物理地址条指令将向物理地址

// // 0X00000F000X00000F00处写处写 1010 个双字个双字}_asm{ mov cx,10a2 : mov eax,es : [ebx]

mov [edi],eax

Page 19: 第 10 章   PC 机的高级编程技术

19

微计算机系统add ebx,4add edi,4loop a2 // // 以上从物理地址以上从物理地址 0X00000F000X00000F00

// // 处依次读出处依次读出 1010 个数据存放在个数据存放在// result// result 数组中数组中

}_asm{ pop es

pop ebp}

printf ( "result=" );for ( int i=0; i<10; i++ )printf ( "%d,",result[i] ); // // 输出结果输出结果return 0;

}

Page 20: 第 10 章   PC 机的高级编程技术

20

微计算机系统10.2.4 保护模式下 Pentium 4 的虚拟页式存储管理

主存

~~

~~

页框

页面程序 1

程序 2

程序 3

Page 21: 第 10 章   PC 机的高级编程技术

21

微计算机系统PGEPCE

831 7 6 5 4 3 2 1 0

MCEPAE PSE DE TSD VMEPVI保留,缺省为全 0 CR4

PAE PSE 物理地址位数 页面大小0 0 32位 4KB0 1 32位 4KB/4MB1 0 36位 4KB1 1 36位 4KB/2MB

Page 22: 第 10 章   PC 机的高级编程技术

22

微计算机系统4KB4KB 分页方式分页方式

31 12 11 9 8 7 6 5 4 3 2 1 0

PWTPCD页表基地址 31~12 PRWUSAVL AD0页目录项PWTPCD页框基地址 31~12 PRWUSAVL AD页表项

31 12 11 9 8 7 6 5 4 3 2 1 0

P=P= 出现位,出现位, US=US= 用户用户 // 监督位,监督位, PCDPCD 是页是页 CacheCache 禁止,禁止, D=Cache“D=Cache“ 脏”脏”位,位, RW=RW= 读读 // 写位,写位, PWT=PWT= 页写贯穿位,页写贯穿位, A=A= 访问位,访问位, AVL=AVL= 用户的操用户的操作系统可用位。而第作系统可用位。而第 77 位(位( PSPS )在)在 4KB4KB 分页中为分页中为 0 0

页目录

32 位线性地址 页目录项号 页面号 偏移

CR3

32 位物理地址

31 22 21 12 11 0

页表

低 12位

高 20位

Page 23: 第 10 章   PC 机的高级编程技术

23

微计算机系统4MB4MB 分页方式分页方式

31 22 8 7 6 5 4 3 2 1 0

PWTPCD页框基地址 31~22 PRWUSAD1页目录项

32 位线性地址 页目录项号 偏移CR

3

32 位物理地址

31 22 21 0

页目录

低 22位高 10位

Page 24: 第 10 章   PC 机的高级编程技术

24

微计算机系统31 5 4 3 2 1 0

PWTPCD32 字节对齐的 PDPT 基地址CR3 寄存器63 36 35 12 11 6 5 4 3 2 1 0

PWTPCD PAVLPDPT项 4KB 对齐的页目录基地址(高 24 位)

63 36 35 12 11 9 8 7 6 5 4 3 2 1 0PWTPCD4KB 对齐的页表基地址 PRWUSAVL A0页目录项PWTPCD4KB 对齐的页框基地址 PRWUSAVL AD页表项

63 36 35 12 11 9 8 7 6 5 4 3 2 1 00G

Pentium III 36Pentium III 36 位地址下的位地址下的 4KB4KB 分页方式地址转换 分页方式地址转换

32 位线性地址页目录项号 页面号 偏移CR3

36 位物理地址

31 30 29 21 20 12 11 0

页目录 页表

PDPT项号

页目录指针表4×64 位 512×64 位 512×64 位

低 12位高 24位

Page 25: 第 10 章   PC 机的高级编程技术

25

微计算机系统

32 位线性地址页目录项号 偏移

CR3

36 位物理地址

31 30 29 21 20 0

页目录

PDPT项号

页目录指针表4×64 位 512×64 位

页目录项 PWTPCD2MB 对齐的页框基地址PRWUSAVL AD

63 36 35 21 20 12 11 9 8 7 6 5 4 3 2 1 0

1G

低 21 位高 15 位

Pentium III 36Pentium III 36 位地址下的位地址下的 2MB2MB 分页方式地址转换 分页方式地址转换

Page 26: 第 10 章   PC 机的高级编程技术

26

微计算机系统

计算机底层硬件操作系统内核与 VxD

操作系统提供的接口应用软件

10.3.1 虚拟机与 VxD 的引入

特权级 3

特权级 0

10.3 Windows 9x 驱动程序编写

Page 27: 第 10 章   PC 机的高级编程技术

27

微计算机系统Windows 9x

SYSVM

Win16 地址空间

Win16 程序Win16 程序Win16 程序Win16 程序

Win32 程序

Win32 地址空间

Win32 程序

Win32 地址空间

……DOSVM

DOS 程序

DOSVM

DOS 程序……

Page 28: 第 10 章   PC 机的高级编程技术

28

微计算机系统10.3.1 保护模式下的 I/O 端口访问 执行 in, out 指令CPL ≤ IOPL?

IOPM相关位 =0?

进行 I/O 操作

否产生一个一般保护异常

是IOPMIOPM 是对所有 VM都起作用的权限机制,它以位( bit )来代表每个端口。某位为 1 ,则该代表的端口被禁止访问;某位为 0;则允许访问该位所代表的端口。

IOPLIOPL 用以表示指定的 I/O 操作处于特权级的哪一级。它在 EFLAGS 中。

CPLCPL当前段的 I/O 优先级,它实际上是 CS 段选择符的第 0~ 第1 位。

Page 29: 第 10 章   PC 机的高级编程技术

29

微计算机系统V86 模式下( DOSVM )的 I/O 端口访问 执行 in, out 指令

IOPM相关位 =0? 进行 I/O 操作否

产生一个一般保护异常

如何捕获一个端口的访问?如何捕获一个端口的访问?

Page 30: 第 10 章   PC 机的高级编程技术

30

微计算机系统

Page 31: 第 10 章   PC 机的高级编程技术

31

微计算机系统10.3.2 保护模式下对中断或异常的处理 外部中断和处理器异常 软中断

CPL ≤门描述符的 DPL ?是

访问各类门描述符 转移后代码段的 DPL≤CPL ?是执行 0 特权级别中的中断处理程序 禁止访问

Page 32: 第 10 章   PC 机的高级编程技术

32

微计算机系统 CPU 根据中断向量表 IDT 调用相应的 VMM异常处理程序,从而切换到 0 特权级别。 其他各种其他各种 VxDVxD 可以通过安装回调例程来响应处理可以通过安装回调例程来响应处理各种异常和中断各种异常和中断,,但是它们不能改变中断描述符表 IDT中给出的各种 VMM异常处理程序。 VMMVMM异常处理程序通过使用异常处理程序通过使用 CALLCALL 指令调用安指令调用安装的各个回调例程装的各个回调例程或自身处理异常。 对于硬件中断, VMM则将控制权交给 VPICD (虚拟可编程中断控制器)处理, VPICD 就调用其他 VxD 通过系统服务 VPICD_Virtualize_IRQ 安装的回调例程处理硬件中断。 一个回调例程要么处理中断和异常,要么忽略该中断,但是它必须使用它必须使用 RETRET 指令返回到 VMM异常处理程序。

Page 33: 第 10 章   PC 机的高级编程技术

33

微计算机系统 VMM异常处理程序使用 IRET 或 IRETD 指令返回到虚拟机中,虚拟机中的应用程序重新获得控制从而继续执行。

Win32程序

虚拟机

VxD 中的回调函数异常处理程序

VPICD

INT x CALL

RETIRET

IRET

硬件中断

RET

Page 34: 第 10 章   PC 机的高级编程技术

34

微计算机系统

思路: 在中断描述符表中构造一个中断门描述符,使它的构造一个中断门描述符,使它的DPL=3DPL=3 ,,这样它就可以被用户级的程序访问,将该中断门描述符的段选择字设为 028H ,显然该选择字对应的代码段在 GDT 中,由于其基地址为 00000000H,段界限为 FFFFFFFFH ,所以现在中断门的偏移量就实际给出了中断处理程序入口的线性地址,我们只要把一个过程作为中断处理程序,这个过程就处在核心级里了。程序如下:

特殊应用:如何利用保护模式下中断的处理特殊应用:如何利用保护模式下中断的处理流程设法使自己从用户级转到核心级?流程设法使自己从用户级转到核心级?

Page 35: 第 10 章   PC 机的高级编程技术

35

微计算机系统#include "stdafx.h"#include <stdio.h>#include <wtypes.h> // wtypes.h// wtypes.h 定义了定义了 DWORDLONG, DWORDLONG,

//DWORD,WORD//DWORD,WORD 等数据类型等数据类型DWORD _cr0; // // 用来保存用来保存 CR0CR0 寄存器的值寄存器的值void _declspec ( naked ) newint3 ( void ) // // 运行在核心级运行在核心级的的

// // 中断中断 33处理程序处理程序{_asm{ mov eax,cr0 // // 这是必须在核心级才能执行的这是必须在核心级才能执行的

// // 特权指令特权指令mov _cr0,eax

}_asm iretd // // 中断返回(中断返回(为什么不是为什么不是 ret?ret? ))}

Page 36: 第 10 章   PC 机的高级编程技术

36

微计算机系统int main ( int argc, char* argv[] ){DWORDLONG idtr,saveidt; WORD newgate[4]={0x0000,0x0028,0xee00,0x0000};

// // 中断门描述符,中断门描述符, DPL=3DPL=3_asm{ sidt idtr // // 将将 IDTRIDTR 的值存在的值存在 idtridtr 变量开变量开

// // 始的始的 66 个字节中个字节中mov ebx,DWORD ptr[idtr+2] // // 把把 IDTIDT 的的

// // 基地址读入基地址读入 EBXEBX 寄存器寄存器add ebx,24 // // 选择中断选择中断 33 作为进入核心级的作为进入核心级的

// // 入口,中断入口,中断 33 的门描述符的门描述符 // // 的地址是的地址是 IDTIDT 基地址加上基地址加上 3*83*8

// // (每个门描述符(每个门描述符 88 个字节)个字节)mov esi,ebxlea edi,saveidt

Page 37: 第 10 章   PC 机的高级编程技术

37

微计算机系统movsd // // 保存原来中断保存原来中断 33 的门描述符的门描述符movsd // // 到到 saveidtsaveidt 中中lea eax,newint3mov newgate,axshr eax,16mov [newgate+6],ax // // 向新的中断描述符中填入向新的中断描述符中填入

// // 中断处理程序的入口偏移量中断处理程序的入口偏移量lea esi,newgatemov edi,ebxmovsd // // 用新中断描述符在用新中断描述符在 IDTIDT 中中movsd // // 替换原来的中断替换原来的中断 33 描述符描述符int 3h // // 触发中断触发中断 33 ,使程序跳转到,使程序跳转到

// 0// 0 级执行中断处理程序级执行中断处理程序

Page 38: 第 10 章   PC 机的高级编程技术

38

微计算机系统lea esi,saveidtmov edi,ebxmovsdmovsd // // 恢复原来中断恢复原来中断 33 的门描述符的门描述符

} printf ( "cr0=0x%x",_cr0 ); // // 输出结果输出结果 return 0;}

Page 39: 第 10 章   PC 机的高级编程技术

39

微计算机系统10.3.3 虚拟设备驱动程序( VxD )基础

1. VxD 的文件结构 VxDVxD 的五个段的五个段 • VxD_CODE VxD_CODE 保护模式下的代码段保护模式下的代码段含设备驱动程序回调例程、服务程序、 API 接口函数和控制程序。• VxD_DATA VxD_DATA 保护模式下的数据段保护模式下的数据段包含设备描述块、服务表、全局变量等。• VxD_ICODE VxD_ICODE 保护模式下的初始化代码段保护模式下的初始化代码段初始化的时候用的服务程序和过程。初始化后被丢弃• VxD_IDATA VxD_IDATA 保护模式下的初始化数据段保护模式下的初始化数据段初始化时用的数据。初始化后被丢弃。• VxD_REAL_INIT VxD_REAL_INIT 实模式下的初始化资料与代码实模式下的初始化资料与代码该过程返回后被丢弃。

Page 40: 第 10 章   PC 机的高级编程技术

40

微计算机系统typedef struct tagDDB {

DWORD DDB_Next; // VMM 使用这一项来指出// 下一个 DDB 的地址

WORD DDB_SDK_Version; // 建立该 VxD 所使用的// SDK/DDK 的版本号

WORD DDB_Req_Device_Number; // 设备 ID 。// UNDEFINED_DEVICE_ID 表示// 不使用唯一 ID

BYTE DDB_Dev_Major_Version; // VxD 的主版本号BYTE DDB_Dev_Minor_Version; // VxD 的次版本号WORD DDB_Flags; // DDB 标志位BYTE DDB_Name[8]; // VxD 的名字,不足 8 个字节必须

// 以空格补满DWORD DDB_Init_Order; // 指定 VxD 的初始化顺序,如果没

// 有特别的初始化要求就使用// UNDEFINED_INIT_ORDER

DWORD DDB_Control_Proc; // 设备控制程序的地址DWORD DDB_V86_API_Proc; // V86API 程序的入口地址

2. VxD 的设备描述符块 DDB

Page 41: 第 10 章   PC 机的高级编程技术

41

微计算机系统DWORD DDB_PM_API_Proc; // 保护模式 API 程序的入口地址DWORD DDB_V86_API_CSIP // V86 入口点的 CS : IPDWORD DDB_PM_API_CSIP; // 保护模式入口点的 CS : IPDWORD DDB_Reference_Data; // 实模式初始化代码设置的参

// 考资料DWORD DDB_VxD_Service_Table_Ptr; // VxD服务表的地址DWORD DDB_VxD_Service_Table_Size; // VxD服务表中提

// 供的 VxD服务的数目} DDB;

Page 42: 第 10 章   PC 机的高级编程技术

42

微计算机系统3. VxD 的加载与卸载 动态加载动态加载API 函数 发的消息 功能

CreateFile Sys_Dynamic_Device_Init 加载 VxDDeviceIOControl W32_DeviceIOControl 与 VxD 进行交互处理

CloseHandle Sys_Dynamic_Device_Exit 卸载 VxD

hDevice=CreateFile ( "\\\\.\\myfirst.vxd", 0, 0, 0, OPEN_EXISTING,

FILE_FLAG_DELETE_ON_CLOSE, 0 );DeviceIoControl ( hDevice,DIOC_MY_IO, NULL, 0, NULL, 0,

NULL,NULL ); CloseHandle ( hDevice );

Page 43: 第 10 章   PC 机的高级编程技术

43

微计算机系统

静态加载静态加载

Page 44: 第 10 章   PC 机的高级编程技术

44

微计算机系统10.4 Windows 2000/XP 设备驱动程序设计 10.4.1 Windows 2000/XP 的设备驱动程序

虚拟设备驱动程序( VDD ) 内核模式驱动程序文件系统驱动程序 保留设备驱动程序 PnP驱动程序 显示驱动程序

WDM 驱动程序类驱动程序 迷你驱动程序

可以使 DOS 应用程序访问 x86平台上的硬件,也可以支持 Windows 9x 下的对端口访问

是一种遵循电源管理协议并能在 Windows 98 和 Windows 2000 间实现源代码级兼容的 PnP 驱动程序

用于显示和打印设备的内核模式驱动程序

在本地硬盘或网络上实现标准 PC文件系统模型(包括多层次目录结构和命名文件概念)

主要包括Windows NT早期版本的驱动程序,它直接控制一个硬设备而不用其他驱动程序帮助,可以不做修改地在 Windows 2000 中运行

Page 45: 第 10 章   PC 机的高级编程技术

45

微计算机系统10.4.2 WDM 的基本结构 1. 1. 基本概念基本概念设备对象设备对象:系统为帮助软件管理硬件而创建的一个数据结构。一个物理设备可以有多个这样的数据结构。物理设备对象物理设备对象:简称 PDO ,处于设备对象栈最底层的设备对象。每个物理设备被创建一个 PDO功能设备对象功能设备对象:简称 FDO ,在 PDO之上,描述设备功能的相关数据结构。过滤器设备对象过滤器设备对象:简称 FiDOs ,在 FDO 的上面或下面,分别称为上层过滤器和下层过滤器。用于修改现有功能驱动程序的行为。设备对象栈设备对象栈:设备对象栈代表处理请求的驱动程序层次。

Page 46: 第 10 章   PC 机的高级编程技术

46

微计算机系统

FiDO

FDO

FiDO

PDO

上层过滤器驱动程序功能驱动程序

下层过滤器驱动程序总线驱动程序

IRP

I/O 系统服务Win32子系统

应用程序

I/O 管理器

用户态核心态

设备对象栈

46页

Page 47: 第 10 章   PC 机的高级编程技术

47

微计算机系统

WDM 驱动程序模型中,每个硬件设备可以有多个驱动程序:功能驱动程序功能驱动程序 :管理 FDO 所代表的设备,负责其初始化、处理 I/O 操作完成时产生的中断事件并为用户提供一种适当的设备控制方式。过滤器驱动程序过滤器驱动程序:用于监视和修改 IRP流。硬件或软件人员可利用过滤器驱动程序修改现有功能驱动程序的行为。总线驱动程序总线驱动程序:负责管理硬件和计算机之间的连接。这个驱动程序实际上和同类设备共同拥有。如 PCI总线驱动程序。

2. 2. 硬件设备的驱动程序种类硬件设备的驱动程序种类

Page 48: 第 10 章   PC 机的高级编程技术

48

微计算机系统

总线驱动程序检测到新的硬件 用户使用控制面板中的“添加新硬件”向导安装一个设备

PnP 管理器为该设备和它的驱动程序在注册表的配置表中添加一些条目 PnP 管理器可能需要调整已经分配给已存在设备的资源,使需要的资源对新设备可用

3. 3. 设备驱动程序安装的顺序设备驱动程序安装的顺序硬件接入

PnP 管理器创建 PDO

Page 49: 第 10 章   PC 机的高级编程技术

49

微计算机系统

驱动程序被装入后,执行 DriverEntry 程序。来设置驱动程序中各个例程的入口地址

PnP 管理器参照注册表中的信息查找与创建的PDO相关的过滤器和功能驱动程序

PnP 管理器装入最底层的过滤器驱动程序并调用其 AddDevice 函数。该函数创建一个 FiDO,从而在过滤器驱动程序和 FiDO之间建立了水平连接

按照 INF文件的指令安装驱动程序

Page 50: 第 10 章   PC 机的高级编程技术

50

微计算机系统

PnP 管理器继续向上执行,依次装入并调用每个低层过滤器、功能驱动程序和每个高层过滤器,直到完成整个设备对象栈

AddDevice把 PDO连接到 FiDO 上

PnP 管理器给设备发送各种 PnP IRP

PnP 管理器给发送“启动设备” PnP IRP告诉驱动程序已经给它分配了哪些资源 ,驱动程序使用这些资源分配启动它的设备 驱动程序处于等待处理 IRP 的状态

Page 51: 第 10 章   PC 机的高级编程技术

51

微计算机系统 当应用程序因要向驱动程序提出各类请求(如读、写数据等)而调用相关函数的时候,就会使得 I/O管理器创建一个 I/O请求包( IRP )。 通常一个 I/O请求包 (IRP)先被送到设备对象栈的最上层驱动程序然后逐渐过滤到下面的驱动程序。每一层驱动程序都可以决定如何处理 IRP ,既可以直接处理完该 IRP 就不再向下传,也可以处理完后继续传递,还可以只做向下传递的工作。 当下层将请求处理完,返回的信息又通过该包的结构逐层向上传递。

4. IRP4. IRP传递的顺序传递的顺序

46页

Page 52: 第 10 章   PC 机的高级编程技术

52

微计算机系统10.4.3 I/O请求包 (IRP)

I/O请求包( IRP )是驱动程序操作的中心,它是一个内核“对象”,是预先定义的数据结构是预先定义的数据结构,,带带有一组对它进行操作的有一组对它进行操作的 I/OI/O 管理器程序管理器程序。 I/O 管理器接收到一个 I/O请求后,在把它传递到合适的驱动程序栈中的最高驱动程序之前,分配并初始化一个 IRP 。一个一个 IRPIRP 有一个固定的首部和一个可变数目的有一个固定的首部和一个可变数目的I/OI/O栈栈。

Page 53: 第 10 章   PC 机的高级编程技术

53

微计算机系统

Page 54: 第 10 章   PC 机的高级编程技术

54

微计算机系统

• 创建异步 IRP 的 IoBuildAsynchronousFsdRequest• 创建同步 IRP 的 IoBuildSynchronous- FsdRequest• 创建同步 IRP_MJ_DEVICE_CONTROL 或 IRP_MJ_

INTERNAL_DEVICE_CONTROL请求的 IoBuildDeviceIoControlRequest

• 创建其他种类 IRP 的 IoAllocateIrp• 创建某些 IRP 的子 IRP 的 IoMakeAssociatedIrp 。

创建 IRP 的可以是 I/O 管理器,也可以是其他的驱动程序。能创建 IRP 的函数有:

Page 55: 第 10 章   PC 机的高级编程技术

55

微计算机系统 在创建一个 IRP时,同时还创建了一个与之关联的 IO_STACK_LOCATION结构数组,它是 I/O栈中的一项,它包含的成员包括 :• MajorFunction (该 IRP 的主功能码)• MinorFunction (该 IRP 的副功能码)• Parameters ( IRP参数)• DeviceObject (与该栈单元对应的设备对象地址)• FileObject (内核文件对象地址)• CompletionRoutine ( I/O 完成程序地址)• Context (任意的与上下文相关的值)。

Page 56: 第 10 章   PC 机的高级编程技术

56

微计算机系统在栈 Parameters 成员中,有几个常用的的参数 :• Create ( IRP_MJ_CREATE请求,创建 IRP )• Close ( IRP_MJ_CLOSE请求,关闭 IRP )• Read ( IRP_MJ_READ请求,读 IRP )• Write ( IRP_MJ_WRITE请求,写 IRP )• StartDevice ( IRP_MJ_PNP 的 IRP_MN_START_DE

VICE请求,启动设备)• DeviceIOControl ( IRP_MJ_IOCTL请求, IOCTL I

RP )。

Page 57: 第 10 章   PC 机的高级编程技术

57

微计算机系统大部分参数可以和 Win32 函数对应起来参数 Win32 API

Creat CreateFile

Read ReadFile

Write WriteFile

DeviceIOControl DeviceIoControl

CloseHandle Close

返回

Page 58: 第 10 章   PC 机的高级编程技术

58

微计算机系统创建完 IRP后,可以使用下面的代码做必要设置,并把

IRP 发送到设备驱动程序。PDEVICE_OBJECT DeviceObject; //// 设备对象结构设备对象结构PIO_STACK_LOCATION stack = IoGetNextIrpStackLocation (

Irp ); //// 获得该获得该 IRPIRP 第一个堆栈单元的指针第一个堆栈单元的指针stack->MajorFunction = IRP_MJ_Xxx;

//// 填充填充 MajorFunctionMajorFunction 代码代码…… //// 可以对栈做其他初始化的工作可以对栈做其他初始化的工作

// // 这里可能运行这里可能运行 StartIoStartIoNTSTATUS status = IoCallDriver ( DeviceObject, Irp );

//// 把把 IRPIRP 发送到设备驱动程序发送到设备驱动程序

返回

Page 59: 第 10 章   PC 机的高级编程技术

59

微计算机系统下面是 IoCallDriver 的执行过程:NTSTATUS IoCallDriver ( PDEVICE_OBJECT device, PIRP Ir

p ){ IoSetNextIrpStackLocation ( Irp ); PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation ( Irp ); //// 获得栈单元指针获得栈单元指针 stack->DeviceObject = device ; //// 设置设备对象结设置设备对象结构地址构地址 ULONG fcn = stack->MajorFunction; //// 得到主功能号得到主功能号 PDRIVER_OBJECT driver = device->DriverObject;

//// 获得驱动程序对象的地址获得驱动程序对象的地址 return ( *driver->MajorFunction[fcn] )( device, Irp );

//// 利用主功能号调用相应的派遣函数利用主功能号调用相应的派遣函数} *driver-> MajorFunction[fcn]*driver-> MajorFunction[fcn] 是函数指针,它所指向的派遣函数是函数指针,它所指向的派遣函数是在是在 DriverEntryDriverEntry 例程中指定的。例程中指定的。返回 Driverentry 返回

Page 60: 第 10 章   PC 机的高级编程技术

60

微计算机系统10.4.4 WDM 驱动程序的结构 WDM 驱动程序包含许多函数(例程),操作系统调用这些例程来执行对 IRP 的各种操作。基本驱动程序函数 I/O 控制函数 派遣函数

DriverEntry

AddDevice

StartIO

AdapterControl

OnInterrupt

DpcForIsr

DispatchPnp

DispatchPowerDispatchWmi

DispatchRead

DispatchWrite

StartIO处理请求队列、 AdapterControl处理 DMA 操作OnInterrupt处理中断。

Page 61: 第 10 章   PC 机的高级编程技术

61

微计算机系统在每个 WDM 驱动程序中,下列函数必须有:• DriverEntry 函数:这个例程是每一个设备驱动程序的入口。在这个例程中完成某些全局初始化工作,还要设置响应各种用户请求的分发例程与 I/O 控制例程的入口。• AddDevice 函数:对于功能驱动程序,其 AddDevice函数的基本职责是创建一个设备对象并把它连接到以

PDO 为底的设备堆栈中。 • DispatchPnp 函数:用于处理 IRP_MJ_PNP消息,以便能实现即插即用的功能。• DispatchPower 函数:用于实现对电源管理的支持。• DispatchWmi 函数: WMI 是微软实现的基于 Web 的企业管理工业标准,该函数用于处理有关的消息。

Page 62: 第 10 章   PC 机的高级编程技术

62

微计算机系统下面是一段下面是一段 DriverEntryDriverEntry 程序的片段程序的片段:extern "C" NTSTATUS DriverEntry ( IN PDRIVER_OBJECT DriverObject, IN PUNIC

ODE_STRING RegistryPath ){ // // 初始化函数的入口地址初始化函数的入口地址 DriverObject->DriverUnload = DriverUnload; DriverObject->DriverExtension->AddDevice = AddDevice; DriverObject->DriverStartIo = StartIo; DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp; DriverObject->MajorFunction[IRP_MJ_POWER]= DispatchPo

wer; DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL]

= DispatchWmi; …… // // 这里可以加入其他这里可以加入其他MajorFunctionMajorFunction处理函数的入口地址处理函数的入口地址

返回

Page 63: 第 10 章   PC 机的高级编程技术

63

微计算机系统

// // 如果驱动程序需要访问设备的服务键,则备份如果驱动程序需要访问设备的服务键,则备份 RegistryPathRegistryPathservkey.Buffer = ( PWSTR ) ExAllocatePool ( PagedPool, RegistryPath->Length+ sizeof ( WCHAR )); if ( !servkey.Buffer ) return STATUS_INSUFFICIENT_RESOURCES; servkey.MaximumLength = RegistryPath->Length + sizeof ( WCHAR ); RtlCopyUnicodeString ( &servkey, RegistryPath ); return STATUS_SUCCESS;}

Page 64: 第 10 章   PC 机的高级编程技术

64

微计算机系统添加一个设备添加一个设备NTSTATUS AddDevice ( PDRIVER_OBJECT DriverObject, PD

EVICE_OBJECT pdo ){ NTSTATUS status; PDEVICE_OBJECT fdo; Status=IoCreateDevice ( DriveObject, sizeof ( WDM_DEVICE_EXTENSION ) , NULL, FILE_DEVICE_UNKNOWN, 0, FALSE, &fdo ); //// 在在 fdofdo 中产生我们的功能设备中产生我们的功能设备对象对象 if ( NT_ERROR ( status )) Return status;……}

Page 65: 第 10 章   PC 机的高级编程技术

65

微计算机系统下面是下面是 IRPIRP 派遣函数的一个框架:派遣函数的一个框架:NTSTATUS DispatchXxx ( PDEVICE_OBJECT device, PIRP Irp){ PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation ( Irp ); //// 获得栈单元指针获得栈单元指针 PDEVICE_EXTENSION pdx = ( PDEVICE_EXTENSION ) device->DeviceExtension; //// 获得设备扩展获得设备扩展 …… //// 其他其他 IRPIRP处理操作处理操作 return STATUS_Xxx; //// 返回状态码返回状态码}

返回

Page 66: 第 10 章   PC 机的高级编程技术

66

微计算机系统

对对 WDMWDM请求包运行机制的总结请求包运行机制的总结1. 应用程序通过 CreateFile等Win32函数来进行有关的请求。

2. I/O 管理器创建 IRP 。3. 设置IRP中的主功能代码和对IRP栈做各种初始化工作。如果需要对 IRP排队,则调用 StartIo处理 IRP队列

4. 将IRP发送到派遣程序(按照 DriverEntry 中指定的入口地址来调用相关的派遣程序)。

5. 执行有关的派遣程序,实际处理对IPR的操作。

Page 67: 第 10 章   PC 机的高级编程技术

67

微计算机系统10.4.5 即插即用 支持即插即用主要是指实现一个 AddDevice 程序和一个 IRP_MJ_PNP处理程序。这个 PnP IRP 有 8 个次功能代码(它们的主功能代码都是 IRP_MJ_PNP )。 ·   IRP_MN_START_DEVICE 分配资源并启动设备·   IRP_MN_QUERY_REMOVE_DEVICE 询问一个设备是否可以删除·   IRP_MN_REMOVE_DEVICE 设备被拔出,删除设备·   IRP_MN_CANCEL_REMOVE_DEVICE 取消查询删除请求·   IRP_MN_STOP_DEVICE 停止设备进行资源重新分配·   IRP_MN_QUERY_STOP_DEVICE 询问设备是否可以停止·   IRP_MN_CANCEL_STOP_DEVICE 取消查询停止请求· IRP_MN_SURPRISE_REMOVAL 用户在意外下拔出设备

Page 68: 第 10 章   PC 机的高级编程技术

68

微计算机系统NTSTATUS DispatchPnp ( PDEVICE_OBJECT fdo, PIRP Irp ){ PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation( Irp ); ULONG fcn = stack->MinorFunction; // // 取副功能码取副功能码 static NTSTATUS status=STATUS_SUCCESSswitch ( fcn ) // // 按照副功能码调用相关的处理函数按照副功能码调用相关的处理函数 { case IRP_MN_START_DEVICE : HandleStartDevice ( fdo,Irp );break; case IRP_MN_QUERY_REMOVE_DEVICE : HandleQueryRemove ( fdo, Irp ); …… }; if ( fcn >= arraysize ( fcntab )) return DefaultPnpHandler ( fdo, Irp ); return status;}

Page 69: 第 10 章   PC 机的高级编程技术

69

微计算机系统10.4.6 数据的读 / 写

WDM 有 4 个标准的资源类型,分别是:• CmResourceTypePort (端口资源)• CmResourceTypeMemory (内存资源)• CmResourceTypeInterrupt (中断资源)• CmResourceTypeDma ( DMA资源)

Page 70: 第 10 章   PC 机的高级编程技术

70

微计算机系统1. 内存与端口访问 尽管 PC 机的 I/O 端口是单独编址的,但为了做到和统一编址的机器兼容性, Windows 2000 的设计者使用了硬件抽象层( HAL )的概念。无论是单独编址还是统一编址,只需要使用下表 8 中所给的函数就可以访问端口和内存了。

Page 71: 第 10 章   PC 机的高级编程技术

71

微计算机系统数据宽度 端口访问函数 内存访问函数

8 位 READ_PORT_UCHARWRITE_PORT_UCHAR

READ_REGISTER_UCHARWRITE_ REGISTER _UCHAR

16 位 READ_PORT_USHORTWRITE_PORT_USHORT

READ_ REGISTER _USHORTWRITE_ REGISTER _USHORT

32 位 READ_PORT_ULONGWRITE_PORT_ULONG

READ_ REGISTER _ULONGWRITE_ REGISTER _ULONG

8 位 字 符串READ_PORT_BUFFER_UCHARWRITE_PORT_BUFFER_UCHAR

READ_ REGISTER _BUFFER_UCHARWRITE_ REGISTER _BUFFER_UCHAR

16 位 字符串READ_PORT_BUFFER_USHORTWRITE_PORT_BUFFER_USHORT

READ_ REGISTER _BUFFER_USHORTWRITE_ REGISTER _BUFFER_USHORT

32 位 字符串READ_PORT_BUFFER_ULONGWRITE_PORT_BUFFER_ULONG

READ_ REGISTER _BUFFER_ULONGWRITE_ REGISTER _BUFFER_ULONG

Page 72: 第 10 章   PC 机的高级编程技术

72

微计算机系统2. 响应中断 响应中断首先要配置中断,也就是截获中断,然后就需要编写中断处理程序。配置中断资源是在 StartDevice 函数中实现的,使用从 CmResourceTypeInterrupt 描述符中得到的参数来调用 IoConnectInterrupt 函数。和实模式下一样,在调用 IoConnectInterrupt 进行中断配置前应该禁止 PC 机的中断,调用之后再允许设备中断。

Page 73: 第 10 章   PC 机的高级编程技术

73

微计算机系统10.4.7 WDM 驱动程序的安装文件 驱动程序根据 INF文件中的指令安装。 INF文件含有安装一个 WDM 设备驱动程序需要的所有必需的信息,包括要复制的文件列表和要创建的注册表项等。 驱动程序可执行文件被复制到正确的位置,通常是Winnt\System32\Drivers目录,然后创建各种注册表项。 INF文件是一个文本文件,它由节组成,每一节从括在方括号中的节名称开始,后面是节的内容,大部分段都含有一系列“ keyword = value” 形式的项。

Page 74: 第 10 章   PC 机的高级编程技术

74

微计算机系统节 项 值 描 述

[Version]

SignatureProviderClassClassGuidDriverVer

$Windows NT$, $Windows 95$ 或 $Chicago$INF文件创建者系统定义的类名字,或用户指定的新的类名字匹配的类 GUID驱动程序的版本号

[Strings] %String%=”Value” 指定一个字符串

[Manufacturer]

%manufacturer%=models 指定厂商名和对应的 models 节的名称

[models] 指定产品名称、对应的 install 节的名称和硬件 ID , 0 个或多个兼容 ID

Page 75: 第 10 章   PC 机的高级编程技术

75

微计算机系统节 项 值 描 述

[install]Copyfiles=@filename | filelistAddreg=addregProfileItems

指定要复制的文件,或列出 filelist 节的名称指定 addreg 节的名称列出指定要添加到“开始”菜单中的项

[DestinationDirs]DefaultDestDir=dirid,[subdir]filelist= dirid,[subdir]

对默认文件复制和 filelist 节中的文件复制,指定目录 ID 和可选的子目录。 dirid是一个目录代码,指示存放文件的标准位置。 Windows 2000DDK 定义了这些代码,如代码 10 表示Windows目录[filelist] 要安装的文件列表

[addreg] 添加新的键和值

Page 76: 第 10 章   PC 机的高级编程技术

76

微计算机系统驱动版的“ Hello World” :1 ,调用 IoCreateDevice()创建一个设备,并返回一个设备对象。2 ,调用 IoCreateSynbolicLink()创建一个符号连接,使 Win32程序可以使用驱动程序3 ,设置 IRP_MJ_DEVICE_CONTROL派遣例程 HelloWorldDispatch() 和卸载例程 HelloWorldUnLoad() 。如果Win32 程序使用 DeviceIoControl() ,则执行 HelloWorldDispatch() 函数4 ,调用 IoGetCurrentIrpStackLocation() 得到当前调用者的 IRP 指针5 ,取得 IO 控制代码,完成后使用 IoCompleteRequest() 完成 IRP 操作如果使用 ControlService() 停止驱动程序,则执行 HelloWorldUnLoad() 函数4 ,调用 IoDeleteSymbolicLink()删除符号连接5 ,调用 IoDeleteDevice()删除已建立的设备

Page 77: 第 10 章   PC 机的高级编程技术

77

微计算机系统驱动入口 DriverEntry()

//创建设备IoCreateDevice(DriverObject, // 驱动程序对象 0, // 扩展设备的大小,由于不需要,所以置 0 &DeviceNameString, // 设备名称 FILE_DEVICE_UNKNOWN, // 设备类型 0, // 指示设备允许的操作 FALSE, // 如果为 TRUE ,表示只能有一个线程使用该设备,为 FALSE ,则没有限制 &lpDeviceObject); //返回的设备对象//创建符号连接IoCreateSymbolicLink(&DeviceLinkString, // 存放符号连接的UNICODE_STRING &DeviceNameString); // 设备名称

Page 78: 第 10 章   PC 机的高级编程技术

78

微计算机系统//派遣例程和卸载例程DriverObject->MajorFunction[IRP_MJ_CREATE]= DriverObject->MajorFunction[IRP_MJ_CLOSE]=DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]=HelloWorldDispatch;DriverObject->DriverUnload=HelloWorldUnLoad;

IRP派遣例程 HelloWorldDispatch()

IrpStack=IoGetCurrentIrpStackLocation(pIrp); // 得到当前调用者的 IRP堆栈// 获取 IO 控制代码,并执行指定操作,这里只是 DbgPrint()IoControlCodes=IrpStack->Parameters.DeviceIoControl.IoControlCode;switch (IoControlCodes) {......

IoCompleteRequest(pIrp,IO_NO_INCREMENT); // 完成 IRP 操作

Page 79: 第 10 章   PC 机的高级编程技术

79

微计算机系统卸载例程 HelloWorldUnLoad()

//删除符号连接和设备IoDeleteSymbolicLink(&DeviceLinkString);IoDeleteDevice(DriverObject->DeviceObject);

Page 80: 第 10 章   PC 机的高级编程技术

80

微计算机系统1 , makefile编译驱动程序,首先应该准备一个 makefile ,这个文件很简单,只有一句代码:## DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source# file to this component. This file merely indirects to the real make file# that is shared by all the driver components of the Windows NT DDK#

!INCLUDE $(NTMAKEENV)\makefile.def

正如描述的那样,不要修改这个文件 ---它是通用的!

Page 81: 第 10 章   PC 机的高级编程技术

81

微计算机系统2 , sources准备的第二个文件就是 sources ,它描述了一些编译的细节。针对本文的程序, sources文件的内容是这样的:TARGETNAME=HelloWorld // 驱动名称TARGETPATH=. // 编译后 SYS 的路径TARGETTYPE=DRIVER // 类型为驱动程序SOURCES= HelloWorld.c // 只有一个源文件

Page 82: 第 10 章   PC 机的高级编程技术

82

微计算机系统