更新日期: 7月 15日 2008年
这个清单提供编码和安装注意事项的简要列表,主要针对正在创建将在 64 位版本 Windows 操作系统上运行的驱动程序开发人员。
此信息适用于以下操作系统:
Microsoft Windows Vista
Microsoft Windows Server 2008
64 位版本的 Microsoft Windows Server 2003
Microsoft Windows XP
本页内容
 64 位 Windows 驱动程序入门
 64 位 Windows 编程模型
 编码指南和移植问题
 64 位 Windows 的驱动程序安装
 开发 64 位驱动程序的参考资料

64 位 Windows 驱动程序入门

预期会有越来越多的领域采用 64 位系统,特别是在企业应用中。随着广泛的设备覆盖和针对 64 位系统的高质量驱动程序变得可用,这种应用将增长得更快。
设备支持 64 位系统的条件是:
  • 确保设备寻址达到 64 位物理内存。
  • 使用 64 位安全编程实践编写 Windows® 驱动程序,并使用 64 位编译器找出问题所属的领域:
    • 记住,Windows Driver Foundation (WDF),Windows Driver Model (WDM) 和工具对于 32 位和 64 位 Windows 都一样。
    • 遵循编码指南,解决与 I/O 控制(IOCTL)、直接内存访问(DMA)和传统设备驱动程序接口(DDI)相关的驱动程序特定的问题。
    • 确保驱动程序支持即插即用和电源管理。
注意,不支持 32 位驱动程序:
  • 内核模式驱动程序运行在与 64 位 Windows 相同的地址空间中。
  • 适应大型系统的驱动程序可以为分页/未分页池和系统缓存使用较大的地址空间。
 返回页首

64 位 Windows 编程模型

Windows 64 位版本由 Windows 编程模型和 Microsoft Win32® API 发展而来。Windows 32 位和 64 位平台基于相同的源代码:
  • 现有的应用程序可以扩展以满足企业需求。
  • 新的设计可以使用巨大的地址空间和内存。
  • 支持现有的 32 位应用程序。
此外:
  • 64 位 Windows 编程模型使用相同的 Win32 DDI 和 API。
  • 在 LLP64(LongLong 和指针)数据模型中,只有指针扩展到 64 位。所有其他的基本数据类型(整型和长整型)的长度保持在 32 位。虽然 64 位指针需要适应具有高达 16 TB 虚拟内存的系统,但是大部分数据仍然在 32 位整数范围内。对于大部分应用程序,将默认整型大小改成 64 位只会浪费空间。
  • 64 位 Windows 编程模型添加大小明确的新数据类型,以及匹配指针精度的新整数类型。类型列表请参见“数据类型”表。
  • 指针长度为 64 位,但是整型和长整型数据类型仍然是 32 位。
  • 大部分内存分配都是 64 位。
  • CPU 掩码扩展到 64 位。
  • I/O 请求和 Unicode 字符串的长度仍然是 32 位。
数据类型
类型名称 类型含义
固定宽度数据类型
 
LONG32、INT32
32 位有符号
LONG64、INT64
64 位有符号
ULONG32、UINT32、DWORD32
32 位无符号
ULONG64、UINT64、DWORD64
64 位无符号
指针精度数据类型
 
INT_PTR、LONG_PTR
有符号整型、
指针精度
UINT_PTR、 DWORD_PTR
无符号整型、
指针精度
SIZE_T
无符号计数、指针精度
SSIZE_T
有符号计数、
指针精度
内存布局
内存 基于 x64 基于 Intel Itanium
用户地址范围
0x10000 0x000007FFFFFEFFFF
0x10000 0x000006FBFFFEFFFF
系统缓存
1 TB
1 TB
超出空间
512 GB
16 GB
系统地址空间(用于内核线程等)
128 GB
128 GB
页大小
4K
8K
分页的池
128 GB
128 GB
未分页的池
在 Windows Vista 和早期系统上占物理内存的 40%,最高达 128 GB;
在 Windows Server 2008、Windows Vista SP1 和以后系统上占物理内存的 75%,最高达 128 GB
在 Windows Vista 和早期系统上占物理内存的 40%,最高达 128 GB;
在 Windows Server 2008、Windows Vista SP1 和以后系统上占物理内存的 75%,最高达 128 GB
物理内存地址
64 位
64 位
 返回页首

编码指南和移植问题

编码指南
  • 使用 Windows 64 位和 32 位安全数据类型。
  • 检查所有指针使用,特别是指针运算。
  • 删除内联汇编代码(使用内部或本机汇编代码)。
  • 对于特定于 x64 的代码,使用:
    #if defined (__AMD64__)
    没有任何 __X64__ 定义可用。
  • 对于特定于 Itanium 代码,使用:
    #if defined(__IA64__)
驱动程序的移植问题
  • 驱动程序应该支持 IOCTL 命令的 32 位和 64 位版本。
    参见“IOCTL 支持”部分。
  • 应该为只能寻址 32 位物理地址的硬件实现 DMA 支持。
    参见“DMA 支持”部分。
  • 指针、多态使用和对齐问题适用于所有驱动程序。
    参见“指针、多态使用和对齐问题”部分。
  • 如有可能,所有驱动程序都应该通过使用 WDF 正确地支持即插即用和电源管理。
    • 在 WDM 驱动程序中,从驱动中心模型过渡到设备中心模型;就是说,处理即插即用和电源管理 I/O 请求包(IRP)或者遵循微型端口指南。
    • 对于打印、扫描和相机,用户模式驱动程序必须是 64 位。
    • 不允许使用传统 API(针对 Windows NT® 4.0)。
  • 对于 64 位微型端口:
    • 遵循 Windows Driver Kit (WDK) 中的微型端口特定的指南。
    • 记住 PAGE_SIZE 的不同(基于 Itanium 的系统上为 8 K,x64 系统上为 4 K)。
    • 指针、多态使用和对齐问题适用于此处。
    • IOCTL、即插即用和 DMA 问题不适用于大部分微型端口。
构建环境和工具
  • 用于 x64 的构建环境是 AMD64。
  • 64 位工具和开发过程与 32 位类似:
    • Debugging Tools for Windows
      使用 64 位版本的 Windows 调试工具能够调试在 64 位处理器上运行的 32 位和 64 位用户模式应用程序。使用这个工具包来调试应用程序和 Windows 64 位上的 Windows 32 位(Windows-32-bit-on-Windows-64-bit,WOW64)模拟器。
      要调试 Intel Itanium 或 x64 处理器上的应用程序,请使用为特定处理器设计的工具包,可以在此处下载:http://www.microsoft.com/whdc/devtools/debugging/install64bit.mspx.
    • WDK 中的交叉编译器
      WDK 中的 64 位构建环境包含一个 64 位编译器,可以用来构建和测试运行在基于 x64 的处理器上的 64 位驱动程序代码。参见 WDK 中的问题和限制(http://msdn.microsoft.com/en-us/library/aa489554.aspx).
    • 已检验版本
      驱动程序开发人员使用 Windows 的已检验版本来识别和诊断操作系统级别的问题。已检验版本中的大部分检查用来确定参数或数据结构中的值是否在期望的特定范围内。详细信息请参见http://www.microsoft.com/whdc/DevTools/tools/chkblds.mspx.
    • Driver Verifier
      这个工具测试和捕获正常操作时通常难以发现的许多情况。Driver Verifier 将验证驱动程序未进行非法的函数调用或引起系统崩溃。它可以识别内存破坏、错误处理的 IRP、无效的 DMA 缓存占用以及可能的死锁等情况。详细信息请参见http://msdn.microsoft.com/en-us/library/ms792872.aspx.
BIOS、ACPI 和补丁注意事项
  • 基于 Itanium 的系统必须支持 ACPI 2.0 64 位表。
  • 64 位 Windows 支持 GUID 分区表(GPT)磁盘。
  • x64 系统上不允许 BIOS 回调。
  • 要与基于 x64 的 Windows 操作系统兼容,驱动程序必须避免以下实践:
    • 修改系统服务表,例如与KeServiceDescriptorTable挂钩。
    • 修改中断调度表 (IDT)。
    • 修改全局描述符表 (GDT)。
    • 使用不是由内核分配的内核堆栈。
    • 修补内核的任何部分(仅限基于 AMD64 的系统)。
    Windows 在 x64 平台上强制执行这些规则。任何这种修改都会导致错误检测。
IOCTL 支持
包含依赖于指针的类型的 IOCTL 结构在 64 位和 32 位应用程序中具有不同的大小。驱动程序在从 32 位线程发出的 IOCTL 和从 64 位线程发出的 IOCTL 之间必须有所不同。驱动程序基于发出方的位宽验证输入和输出缓冲区的长度。
驱动程序可以使用三种可能的解决方案中的任意一种来同时支持 32 位和 64 位调用者:
  • 避免在 IOCTL 结构中使用指针类型。
  • 使用 IoIs32bitProcess() API。
  • 在 IOCTL 代码的 Function 代码字段中为 64 位调用者定义一个位。
要使用 IoIs32BitProcess(),在代码中定义一个 32 位 IOCTL 结构,然后确定发出进程是 32 位还是 64 位。
头文件中的 IOCTL 结构:
typedef struct _IOCTL_PARAMETERS {    PVOID   Addr;    SIZE_T  Length;    HANDLE  Handle;} IOCTL_PARAMETERS, *PIOCTL_PARAMETERS;
32 位 IOCTL 结构:
 This structure is defined // inside the driver source code//typedef struct _IOCTL_PARAMETERS_32 {    VOID*POINTER_32  Addr;    INT32            Length;    VOID*POINTER_32  Handle;} IOCTL_PARAMETERS_32, *PIOCTL_PARAMETERS_32;
使用 IoIs32BitProcess 的 32 位和 64 位 IOCTL 例子:
#ifdef _WIN64case IOCTL_REGISTER:if (IoIs32bitProcess(Irp)) {  /* If this is a 32 bit process */               params32 =    (PIOCTL_PARAMETERS_32)(Irp>AssociatedIrp.SystemBuffer);  if(irpSp->Parameters.DeviceIoControl.InputBufferLength <                    sizeof(IOCTL_PARAMETERS_32)) {         status = STATUS_INVALID_PARAMETER;       } else {       LocalParam.Addr = params32->Addr;        LocalParam.Handle = params32->Handle;            LocalParam.Length = params32->Length;     /* Handle the ioctl here */        status = STATUS_SUCCESS;        Irp->IoStatus.Information = sizeof(IOCTL_PARAMETERS);    }} else { /* 64bit process IOCTL */  params = (PIOCTL_PARAMETERS)           (Irp->AssociatedIrp.SystemBuffer);  if (irpSp->Parameters.DeviceIoControl.InputBufferLength                            < sizeof(IOCTL_PARAMETERS)) {         status = STATUS_INVALID_PARAMETER;                   } else {                            RtlCopyMemory(&LocalParam, params,sizeof(IOCTL_PARAMETERS));     /*  Handle the ioctl here */     status = STATUS_SUCCESS;    }    Irp->IoStatus.Information = sizeof(IOCTL_PARAMETERS);}break;
如果选择为 64 位调用者定义一个位,那么使用 Function 字段中的高位。
当前 IOCTL 码有 5 个字段,包括一个 11 位的 Function 字段:
Device Type (16) Access (2) Custom (1) Function (11) Method (2)
新的 IOCTL 码使用 Function 字段中的高位来指示 64 位调用者:
Device Type (16) Access (2) Custom (1) 64Bit (1) Function (10) Method (2)
DMA 支持
  • 使用 PHYSICAL_ADDRESS 类型定义来访问物理地址。PHYSICAL_ADDRESS 为 64 位长。
  • 将所有 64 位视为一个有效的物理地址。不要忽略高端的 32 位。
  • 使用内核模式驱动程序框架(KMDF)或 Windows DMA DDI 来确保在所有平台上正确运行。当使用 KMDF 或 Windows DMA 例程时,Windows 处理大小问题。
  • 在合适的时候使用分散/聚集 DMA。
  • 通过使用具备 64 位寻址能力的设备极大地提高性能。
指针、多态使用和对齐问题
指针大小在应用程序和驱动程序中一样。用于移植应用程序的指南在下列情况中也适用于驱动程序:
  • 多态数据使用(与指针大小相关)。
  • 对齐问题。
  • 常量和宏运算。
本节讨论前两种情况。第三种情况在 MSDN® 文章“超越 Windows XP:现在准备好迎接 64 位版本 Windows 的到来”中讨论。
多态数据使用
  • 不要将指针强制转换成 int、long、ULONG 或 DWORD。
    使用 UINT_PTR、INT_PTR、ULONG_PTR 等。
    例如:
    Copy Code
    ImageBase = (PVOID) ((ULONG)ImageBase | 1);

    应该改写成:
    Copy Code
    ImageBase = (PVOID) ((ULONG_PTR)ImageBase | 1);

  • 使用 PtrToUlong()PtrToLong() 截断指针:
    • 决不要将存储已截断指针的 int 或 ULONG 强制转换回指针。
    • 计算缓冲区大小时应该小心;大小可能超出 ULONG 的容量。
  • 当调用具有指针 OUT 参数的函数时,应小心地使用正确的大小:
    Copy Code
    void GetBufferAddress(OUT PULONG *ptr);{*ptr=0x1000100010001000;}void foo(){  ULONG bufAddress;  //  // this call causes memory corruption  //  GetBufferAddress((PULONG*)&bufAddress);}

对齐问题
基于 Itanium 的系统需要自然对齐内存引用(也就是说,以 4 字节为边界访问 32 位)。错误对齐的内存引用在基于 Itanium 的系统上引发一个异常并对系统进行错误检测。
虽然 x64 更宽容,但要获取更好的性能,也需要对齐。
  • 使用结构封装的指令时,应意识到对齐问题。
  • 如果在单个头文件中使用不同的封装级别,应该格外小心。
  • 为了获得最佳的结果,将 64 位值和指针放在结构的开始处。
  • RtlCopyMemory()memcpy() 不会发生错误。
  • 使用 UNALIGNED 宏修复对齐问题:
    Copy Code
    #pragma pack (1) /* also set by /Zp switch */struct AlignSample {ULONG size;void *ptr;  };struct AlignSample s;void foo(void *p) {*p = p;// causes alignment fault...}foo((PVOID)&s.ptr);void foo(void *p) {struct AlignSample s;     *(UNALIGNED void *)&s.ptr = p; }

有关对齐的更多信息,请参阅“ 内存管理:每个驱动程序作者都需要知道的技巧。”
更多编码问题
  • 仔细地检查:
    • 含指针的显式和隐式联合体。
    • 存储在磁盘上或与 32 位进程进行交换的数据结构。
    • 安全描述符。
    • 处理内存区域大小的代码:
      len = ptr2 - ptr1
      len 可以大于 2^32
  • 截断执行控制代码为 32 位。
  • 使用 piecemeal-size 分配:
    Copy Code
    struct foo {
    DWORD NumberOfPointers;
    PVOID Pointers[1];
    } xx;
    Wrong:
    malloc(sizeof(DWORD)+100*sizeof(PVOID));
    Correct:
    malloc(FIELD_OFFSET(struct foo,Pointers)
    +100*sizeof(PVOID));

  • 小心使用十六进制常量和无符号值。
  • 当您使用无符号数作为下标时,应小心操作:
    • DWORD index = 0;
    • CHAR *p;
      表达式 if (p[index - 1] == '0') 将会在 Itanium 系统造成存取违规:
      在 32 位机器上: 在 64 位机器上:
      p[index-1] == p[0xffffffff] == p[-1] p[index-1] == p[0x00000000ffffffff] != p[-1]
其他注意事项
  • -1 != 0xFFFFFFFF
    0xFFFFFFFF != 无效句柄
  • DWORD 始终是 32 位。不要使用 DWORD 变量来存储指针或句柄。
  • 将指针强制转换成 PCHAR 用于指针运算:
    Copy Code
    ptr = (PVOID)((PCHAR)ptr + pageSize);

  • 在调试语句中使用 %I 打印指针。
  • 大于等于 0x80000000 的地址不一定是内核地址。
 返回页首

64 位 Windows 的驱动程序安装

64 位驱动程序 INF 需求
Windows Server 2003 SP1 和更高的 Windows 版本不会在基于 x64 的系统上安装带有未修饰 INF 节的驱动程序包。
为了与 Intel Itanium 系统兼容,Windows Server 2003 SP1 将安装带有未修饰 INF 节的驱动程序包。但是,Windows 硬件徽标计划需要 INF 修饰,所以带有未修饰 INF 节的驱动程序包无法满足徽标的资格要求。
INF 的 [Manufacturer] 节条目和 [Models] 节名称必须针对将要安装在基于 x64 的系统上的驱动程序包添加修饰,而且应该针对基于 Intel Itanium 的系统添加修饰。原始发布版 Windows XP 之后的所有 Windows 版本都支持这些修饰;因此,通过这种方式修饰的非 x86 系统 INF 将适用于所有已发布的基于 NT 的 Windows 操作系统。
目标是防止安装错误的驱动程序二进制文件,因为客户不了解平台之间的差别。
  • 使用 Windows XP 中引入的 TargetOsVersion。
  • 在 Windows Server 2003 SP1 和以后的版本中,必须为 64 位平台修饰 [Manufacturer] 和 [Models] INF 节。例如:
    Copy Code
    [Manufacturer] %mycompany% = MyCompanyModels, NTamd64 [MyCompanyModels.NTamd64] %MyDev% = mydevInstall, mydevHwid

32 位和 64 位平台的驱动程序安装
为了简化从 32 位安装程序安装 64 位驱动程序的过程,Microsoft 在 WDK 中提供 Driver Install Frameworks (DIFx) 工具的 64 位版本。DIFx 工具包括:
  • Driver Package Installer (DPInst)。
  • Driver Installation Frameworks for Applications (DIFxApp)。
无需为 64 位平台编写单独的 64 位安装程序,可以从单个 32 位安装程序启动 DPInst 或 DIFxApp 的正确版本。
无法使用 32 位驱动程序安装包直接安装 64 位驱动程序,但是可以使用它们确定当前正在运行哪个体系结构,然后启动合适的安装程序。在 64 位平台上,32 位安装程序在 WOW64 下运行,WOW64 就是让基于 Win32 的应用程序在 64 位 Windows 上运行的 x64 模拟器。安装程序必须能够检测其运行的平台,从而能够为该平台安装正确的驱动程序包。
 返回页首

开发 64 位驱动程序的参考资料

  • WDK 中的“64 位问题”
  • IA-64 系统和 ACPI 2.0 64 位表格
  • 进一步了解 Windows 内存管理
  • 超越 Windows XP:现在准备好迎接 64 位版本 Windows 的到来
  • KMDF 驱动程序中的 DMA 支持
  • WHDC Web 站点上与硬件相关的信息
  • 64 位系统的 INF 需求
  • 基于 x64 的系统的修补策略
  • 64 位 Windows 编程指南
  • 内存管理:每个驱动程序作者都需要知道的技巧

转载于:https://blog.51cto.com/y5023/897878

64 位 Microsoft Windows 驱动程序清单相关推荐

  1. 64位处理器_32位和64位的Windows 10和处理器(CPU)有什么区别

    当你下载Windows 10.Office或任何其他软件时,可能会注意到有32位和64位版本可用,这时你可能会想到一个问题,我需要哪个? 在本文中,你可以了解32位和64位Windows 10之间的区 ...

  2. 64位win7禁用驱动程序签名强制

    64位win7禁用驱动程序签名强制 其实想要在64位win7中使用未有签名的驱动程序还是有很多方法的,如上图中,开机之后在登录等待界面按下F8键,进入Windows系统的高级启动项,我们会发现与原有的 ...

  3. 如何通过使用 64 位版本 Windows 查看系统注册表 WOW6432Node

    64 位版本 Windows 中的注册表分为 32 位注册表项和 64 位注册表项.许多 32 位注册表项与其相应的 64 位注册表项同名,反之亦然. 64 位版本 Windows 包含的默认 64 ...

  4. CY7C68013A在WIN7下64位的USB驱动程序安装过程

    文章来源说明:CY7C68013A在WIN7下64位的USB驱动程序安装过程遇到好几个问题,在网络上查阅了不少资料,本人只是对网络上的资料进行了整理,不能算是原创,对引用部分均说明了来源,为避免大家重 ...

  5. 在64位的Windows Server 2008 for Itanium-Based Systems 安装JDK

    在oracle官方下载的JDK1.7和1.8不管是64位的还是32位的,安装在64位的Windows Server 2008 for Itanium-Based Systems,都会报错.64位的报错 ...

  6. 64位win7禁用驱动程序签名强制 几种常用方法

    Driver Signature Enforcement Overrider http://www.oyksoft.com/soft/8350.html 其实想要在64位win7中使用未有签名的驱动程 ...

  7. 如何在64位的windows平台上安装需要c编译的python扩展库

    以在64位windows 7上,编译安装greenlet为例   1 最新的2.7.6版本有问题,卸载换2.7.5,问题在于字符编码没解决   2 安装64位版本的Windows SDK,地址如下: ...

  8. Oracle10g 64位 在Windows 2008 Server R2 中的安装 解决方案

    背景: 操作系统Windows 2008 Server R2 要安装Oracle10g 64位版本 安装时出现如下错误: 检查操作系统版本:必须是5.0,5.1,5.2 or 6.0.实际为6.1 未 ...

  9. 如何让64位的windows上的IIS可以运行32位的程序

    在最近的工作中,引用了一个外部的组件,然而由于那个外部组件只能在32位环境中运行,当我们的程序布署到64位的环境中时,就不能工作了.由于那个组件是在服务中引用的,我们的服务是宿主在IIS中的,而这时的 ...

  10. java jdk 1.8 配置_Java开发环境jdk 1.8安装配置方法(Win7 64位系统/windows server 2008)...

    什么是jdk jdk是什么呢?jdk的是java development kit的缩写,意思是java程序开发的工具包.也可以说jdk是java的sdk. 目前的JDK大致分三个大版本: Java S ...

最新文章

  1. 阿里首次公开量子通信技术 为20年后做准备
  2. linux安装软件命令1003无标题,linux系统安装OFED(infiniband)
  3. sql能查到数据 dataset对象里面没有值_新零售数据分析报告
  4. 表的插入、更新、删除、合并操作_21_合并表中数据
  5. MapReduce:处理数据密集型文本处理–局部聚合第二部分
  6. 100亿估值的文和友,为何难以“走出”长沙?
  7. python3 面向对象、类、继承、组合、派生、接口、子类重用父类方法
  8. python的前端和后端_前端与后端的数据交互(jquery ajax+python flask)
  9. 矩阵乘法 算法训练 试题_计算方法练习题及答案汇总(共八套).docx
  10. 接口测试流程及常见问答
  11. 开发中的各种时间格式转换(一)
  12. android壁纸制作,安卓动态壁纸制做壁纸的方法教程
  13. RK987蓝牙机械键盘win和alt键互换
  14. 30系 显卡显存被占用又找不到进程的解决办法
  15. 防范映像劫持(IFEO HIJACK)
  16. Typora自定义样式--你值得拥有自己的styles
  17. python写网络爬虫编程环境设置
  18. JAVA企业面试题精选 JDBC 1-10
  19. 插值和拟合MATLAB
  20. 试玩接入vungle技巧

热门文章

  1. 如何添加BigBoss的Cydia源地址
  2. 项目质量管理可能存在的问题及应对策略
  3. 明明办了100M宽带,下载速度为何不到10M/s?
  4. efi分区能不能删除 win10_Win10删除了EFI分区:以下是恢复它的方法
  5. 【漏洞利用】逻辑漏洞之任意账号密码重置详解
  6. Xilinx FPGA的Device DNA获取方法
  7. Studio One5中文电脑音乐制作宿主软件保卫萝卜
  8. 萝卜内存对比工具使用说明
  9. 常见的web网站攻击类型
  10. Java使文本框失去焦点的方法,使文本框失去焦点的事件是()A.ChangeB.FocusC.SetFocusD.LostFocus...