VS2008 开发驱动程序

1.       前言

 

随着计算机科学技术的发展,驱动程序的开发悄然成为各个计算机应用领域(特别是编写与硬件相关程序)的程序员的关注的话题,对于那些迫切希望探究驱动程序开发奥秘的程序员来讲,面对铺天盖地,五花八门的各种图书资料,难免出现不知从何入手的问题,本文将带领你利用微软成熟的开发设计环境,自己动手开发出几类最简单的驱动程序,抛砖引玉,希望大家能够从中吸取到自己需要的知识,戳破驱动程序开发神秘的面纱,提升自身软件设计实力,为祖国的软件事业发展做出更大的贡献。

本人在学习驱动程序开发伊始,懵懵懂懂中也翻阅了不少前辈们的书籍,也在互联网上搜集了不少关于驱动开发方面的资料,出处无法一一列举,本文也将引用或者参考部分内容,在此感谢原著对本人的帮助,对前辈们献上我最崇高的敬意。

2.       开发环境搭建

 

2.1   软件平台搭建

Microsoft Visual Studio 2008 , WDK7,VMware Workstation6.5.

安装VS2008MSDN MSDN 可以帮助你更好使用VS2008,在出现问题找不到答案时,可以仔细阅读一下MSDN ,会提供一些必要的帮助。并且可以通过MSDN免费得到WDK7的下载连接。VS2008安装步骤略。

下载,安装WDK7,即(Windows Driver Kits 7.0.0)。提示选择安装选项时,建议全部选择安装,WDK便自动安装WinDbg(Windows调试工具),用于使用虚拟机对驱动程序代码进行调试。安装步骤略。

安装VMware Workstation.建议选择安装6.0以上版本。安装步骤略。安装成功以后新建Windows虚拟机,笔者选择的是WindowsXP系统(其他Windows系统大体相同),并安装系统映像,使之成为可以正常工作的WindowsXP虚拟系统。

2.2   调试平台搭建:

软件平台搭建成功以后,调试平台的搭建需要以下几个步骤。

第一步,修改WindowsXP虚拟机的系统配置。

1.       修改虚拟机配置。在硬件中选择添加串口。在连接属性中选择“使用命名管道”。保留默认命名管道名称//./pipe/com_1。在串口端属性中选择“The end is the server.”,“The other end is an application. ”。勾选I/0模式中的”Yield CPU on Polled”复选框。

2.       启动虚拟机进入WindowsXP系统,打开“我的电脑”窗口,在“工具”菜单里面选择“文件夹选项”并点击,在文件夹选项弹出窗口选择“查看”选项卡。在“高级选项”中去除“隐藏受保护的操作系统文件”复选框勾选。并选择“显示所有文件和文件夹“。确定后系统关闭弹出窗口。

3.       打开系统的安装分区,笔者电脑默认安装的C盘。在根目录下可以找到“boot.ini”配置文件。双击打开文件。修改[boot loader]Timeouts = 30.修改[Operating systems],复制其中关于WindowsXP 的一行字符(如果是纯净系统只有一行系统描述,有些系统可能带有DOS安装工具的选项,我们只需要复制关于安装Windows系统的描述),添加一新行并粘贴复制描述字符串。在系统描述字符串里面添加“-Debug”以示和前面项目的区别,行末添加“/debug /debugport=COM1 /baudrate=115200 。保存关闭文件。关闭系统。

4.       从开始菜单中选择“Debugging Tools for WindowsX86)”中的windbg并打开。

file 菜单下的Symbol Search Path项点击,弹出Symbol Search Path对话框。在Symbol Path编辑框里面输入srv*c:/windows/symbols*http://msdl.microsoft.com/download/symbols;cache*c:/windows/symbols。并新建C:/Windows/symbols文件夹。在file 菜单下选择Kernal Debug选项,弹出Kernal Debugging对话框,选择COM选项卡,输入波特率为115200,端口名//./pipe/com_1 勾选Pipe复选框。确定后WinDbg即处于等待管道连接状态。

5.       重新启动WindowsXP虚拟机。在引导列表(即可看到我们在第3步中添加的系统描述)中,选择带有“-Debug”选项(前面设置哪项)并回车。正常情况下,在启动一段时间后WinDbg即显示连接成功。选择WinDbg中的Debug菜单下break选项,如果虚拟机响应,WinDbg调试菜单和工具栏即变为有效状态,可以进行单步等其他操作。说明调试平台搭建成功。首次进行连接可能需要较长时间。

3.       KDM驱动开发示例

 

3.1   项目属性配置

1.       打开VS2008,新建一个Visual C++  à  Win32 à win32空项目。例如DDKDemo

2.       打开VS2008 的“生成”菜单中的“配置管理器”选项。在活动解决方案配置中选择《新建》,新建一个Check空的解决方案配置。

3.       在解决方案管理器中,新建一个DDKDemo.h头文件,一个DDKDemo.cpp源文件。

4.       打开VS2008的“项目”菜单里面“属性”选项。即打开Test项目属性页。在项目属性页选择“配置属性”,打开十字图标。

5.       选择“C/C++”并展开内部选项。

在“常规”选项中,在“附加包含目录”中添加wdk 引用头文件目录。并去除“从父级或项目默认设置继承”复选框的勾选。Wdk头文件目录如下:

                       D:/WinDDK/7600.16385.0/inc/api

                      D:/WinDDK/7600.16385.0/inc/crt

                      D:/WinDDK/7600.16385.0/inc/ddk

                      注意笔者的WDK安装目录在D盘。

             在“调试信息格式”中选择 C7 兼容(/Z7)”选项。

             在“警告等级”中选择“3级(/W3)”。

             在“将警告视为错误”中选择“是(/WX)”。

在“优化”选项中,在“优化”中选择“禁用(/Od)”。

在“预处理器”选项中,在“预处理器定义”中添加                  WIN32=100;_X86_=1;WINVER=0x501;DBG=1”。并去除“从父级或项目默认属性继承”复选框的勾选。

在“高级”选项中,选择“调用约定”为“__stdcall  (/Gz)”。

6.       选择“链接器”并展开内部选项。

在“常规”选项中,修改“输出文件”的文件扩展名为 .sys 添加“附加库目录”

                       D:/WinDDK/7600.16385.0/lib/Crt/i386

                       D:/WinDDK/7600.16385.0/lib/wxp/i386

并去除“从父级或项目默认设置继承”复选框的勾选。

在“输入”选项中,添加“附加依赖项”ntoskrnl.lib并去除“从父级或项目默认设置继承”复选框的勾选。

在“清单文件”选项中,选择“生成清单”为否。

在“调试”选项中,选择“生成调试信息”为“是 /Debug)”。

在“系统”选项中,选择“子系统”为“本机 /SUBSYSTEM:NATIVE)”。选择“驱动程序”为“驱动程序(/DRIVER)”。

在“高级”中,添加“入口点”为DriverEntry。选择“随即基址”为“默认值”。选择“数据执行保护”为默认值。选择“目标计算机”为“MachineX86(/MACHINE:X86)”。

在“命令行”选项中,添加“/SECTION:INIT,D /IGNORE:4078”。

3.2   示例代码简介

/*********************************************************************

** 文件名:DDKDemo.h

** 注释:这是一个KDM的测试程序--用于对设备驱动程序本质进行必要的了解

** 作者:XPJ

** 创建时间:2009-11-10

*********************************************************************/

 

#pragma once

 

//KDM驱动程序头文件

extern "C"

{

 

#include

 

}

 

//定义几个函数段属性宏

#define PAGEDCODE code_seg("PAGED")                   //分页内存段

#define LOCKEDPAGE code_seg()                    //非分页内存段

#define INITCODE code_seg("INIT")                //初始化内存段

 

//定义设备扩展结构,用于保存设备属性

typedef struct _DEVICE_EXTENSION

{

  PDEVICE_OBJECT pDeviceObject;                  //设备对象指针

  UNICODE_STRING ustrDeviceName;                 //设备名

  UNICODE_STRING ustrSymbolicName;          //符合连接名

}DEVICE_EXTENSION,*PDEVICE_EXTENSION;

 

//辅助创建设备函数声明

NTSTATUS CreateDevice(IN PDRIVER_OBJECT pDriverObject);

//驱动卸载回调函数

VOID DDKUnload(IN PDRIVER_OBJECT pDriverObject);

//驱动投递函数

NTSTATUS DDKDispatchRoutine(IN PDEVICE_OBJECT pDeviceObject,

                              IN PIRP pIrp);

 

/*********************************************************************

** 文件名:DDKDemo.cpp

** 注释:DDKDemo实现文件

** 作者:XPJ

** 创建时间:2009-11-10

*********************************************************************/

 

#include "DDKDemo.h"

 

#pragma INITCODE

extern "C" NTSTATUS DriverEntry(

       IN PDRIVER_OBJECT pDriverObject,

       IN PUNICODE_STRING ustrRegistryPath)

/*++

功能描述:驱动入口函数。

 

 

参数:

       pDriverObject:驱动对象指针。

       pRegistryPath:驱动注册表项路径字符串。

 

 

返回值:

       成功返回:STATUS_SUCCESS

 

 

--*/

{

  NTSTATUS status;

  DbgPrint(("Hello,My Windows!Enter DriverEntry!/n"));

 

         //添加一个调试断点,用于使用WinDbg进行源代码调试

  DbgBreakPoint();

  //注册其他驱动回调函数入口

  pDriverObject->DriverUnload=DDKUnload;

  pDriverObject->MajorFunction[IRP_MJ_CREATE]=DDKDispatchRoutine;

  pDriverObject->MajorFunction[IRP_MJ_CLOSE]=DDKDispatchRoutine;

  pDriverObject->MajorFunction[IRP_MJ_WRITE]=DDKDispatchRoutine;

  pDriverObject->MajorFunction[IRP_MJ_READ]=DDKDispatchRoutine;

 

  //创建设备

  status=CreateDevice(pDriverObject);

  DbgPrint(("DriverEntry end!/n"));

 

  return status;

}

 

#pragma INITCODE

NTSTATUS CreateDevice(IN PDRIVER_OBJECT pDriverObject)

/*++

功能描述:辅助创建设备对象函数。

 

 

参数:

       pDriverObject:驱动对象指针。

 

 

返回值:成功    返回STATUS_SUCCESS

       失败 返回错误信息

      

 

 

--*/

{

  NTSTATUS status;

  PDEVICE_OBJECT pDeviceObject;

  PDEVICE_EXTENSION pDeviceExtension;

 

  DbgPrint(("Enter CreateDevice!/n"));

  //创建设备名称

  UNICODE_STRING DeviceName;

  RtlInitUnicodeString(&DeviceName,L"//Device//DDKDevice");

 

  //创建设备

  status=IoCreateDevice(pDriverObject,

       sizeof(DEVICE_EXTENSION),

       &(UNICODE_STRING)DeviceName,

       FILE_DEVICE_UNKNOWN,

       0,TRUE,

       &pDeviceObject);

  if(!NT_SUCCESS(status))

  {

       return status;

  }

 

  //添加扩展属性

  pDeviceObject->Flags |= DO_BUFFERED_IO;

 

  //创建符合连接

  UNICODE_STRING SymbolicLinkName;

  RtlInitUnicodeString(&SymbolicLinkName,L"//??//MyDDKDevice");

 

 

  pDeviceExtension=(PDEVICE_EXTENSION)pDeviceObject->DeviceExtension;

  pDeviceExtension->pDeviceObject=pDeviceObject;

  pDeviceExtension->ustrDeviceName=DeviceName;

  pDeviceExtension->ustrSymbolicName=SymbolicLinkName;

 

  status=IoCreateSymbolicLink(&SymbolicLinkName,&DeviceName);

  if(!NT_SUCCESS(status))

  {

       IoDeleteDevice(pDeviceObject);

       DbgPrint(("CreateDevice Failed!/n"));

       return status;

  }

  DbgPrint(("CreateDevice end!/n"));

  return STATUS_SUCCESS;

}

 

#pragma PAGEDCODE

VOID DDKUnload(IN PDRIVER_OBJECT pDriverObject)

/*++

功能描述:驱动卸载函数。

 

 

参数:

       pDriverObject:驱动对象指针。

 

 

返回值:无

      

 

 

--*/

{

  PDEVICE_OBJECT pNextObject;

  DbgPrint(("Enter DDKUnload/n"));

  pNextObject=pDriverObject->DeviceObject;

  while(pNextObject !=NULL)

  {

       //遍历所有挂载设备

       PDEVICE_EXTENSION pDevExtension=(PDEVICE_EXTENSION)pNextObject->DeviceExtension;

       UNICODE_STRING SymLink=pDevExtension->ustrSymbolicName;

       IoDeleteSymbolicLink(&SymLink);

       pNextObject=pNextObject->NextDevice;

       IoDeleteDevice(pDevExtension->pDeviceObject);

  }

 

 

}

 

#pragma PAGEDCODE

NTSTATUS DDKDispatchRoutine(IN PDEVICE_OBJECT pDeviceObject,

                              IN PIRP pIrp)

/*++

功能描述:驱动投递函数。该驱动所有IRP请求公有投递函数。

 

 

参数:

       pDriverObject:驱动对象指针。

       pIrp:IRP请求。

 

 

返回值:返回STATUS_SUCCESS

      

 

 

--*/

{

  DbgPrint(("Enter DDKDispatchRoutine!/n"));

  NTSTATUS status=STATUS_SUCCESS;

 

  pIrp->IoStatus.Status=status;

  pIrp->IoStatus.Information=0;

  IoCompleteRequest(pIrp,IO_NO_INCREMENT);

 

  DbgPrint(("DDKDispatchRountine end!/n"));

  return status;

}

3.3   安装调试示例

打开DDKDemo所在目录,进入Check文件夹,复制DDKDemo.sys文件到虚拟机中。

驱动的安装可以有二种选择,一种使用安装工具进行安装,一种自己编写安装程序。对于初学者,可以从网上下载DriverMonitor驱动调试安装工具来安装自己生成的驱动程序。

打开WinDbg,在file菜单中打开Source Search Path项,在弹出的对话框的Source Path中添加DDKDemo目标文件夹全路径,即上述的Check文件夹的全路径。在Debug菜单中选择Source Mode为选择状态,启动Kernal Debug 内核调试。

WindowsXP虚拟机中安装加载DDKDemo.sys驱动程序,驱动程序被加载以后,虚拟机即在我们设置的断点中断,同时WinDbg处于激活状态。在WinDbg中选择单步执行,单步两下,WinDbg即可弹出附带源码的驱动程序调试窗口。现在你已经进入里系统驱动加载的过程中了,可以随意查看程序执行过程中的参变量的变化。接下来就是你自己施展才华时候了。呵呵~~ 展开阅读全文

  • 点赞
  • 评论 2
  • 分享
    x

    海报分享

    扫一扫,分享海报

  • 收藏
  • 手机看

    分享到微信朋友圈

    x

    扫一扫,手机阅读

    • 打赏
    • 文章举报

    打赏

    xpj1983

    “你的鼓励将是我创作的最大动力”

    5C币 10C币 20C币 50C币 100C币 200C币

    确定

  • 关注
收起全文

Linux设备驱动开发入门

01-20
还能输入1000个字符

huangxy10的专栏

11-11 8239

[Windows驱动开发](一)VS2008搭建windows驱动编译环境

开发windows驱动的第一步当然是要学会如何编译windows驱动程序。编译windows程序的方式大约有以下几种:    ● WDK提供的Build Environments:微软官方推荐使用WDK提供的Build Environments来对相应系统编译驱动,此方法需要用户自行创建Source文件编译,对于不熟悉的人略显困难    ● VS...

相信未来!

02-28 1220

VS2008+WDK+Win7 32位 驱动开发环境配置中遇到的问题

初次,接触驱动开发,第一步便是配置开发环境。期间遇到了一些问题,并收获了一些知识,特记录下来以备它日之用。1)PREfast是一个C++代码静态分析工具;   备注:取消选择 Create PREfast configuration 项,否则编译后会出问题,很多网友不明白为什么不能选此项,其实原因很简单。    因为PREfast是一个C++代码静态分析工具,只有在较新的DDK中比...

linux嵌入式开发+驱动开发视频精讲

04-27

Android底层技术:Linux驱动框架与开发

09-22

Android底层技术:HAL驱动开发

09-22

嵌入式Linux驱动教程(韦东山2期)

07-07

yangyang_1980_ren的专栏

10-10 180

VS2008编译驱动程序的配置方法

编译驱动程序的常用方法有两种,一种是通过WDK/DDK的COMMAND环境进行编译,另外一种是通过Visual Studio系列软件实现界面编译。通过VisualStudio编译驱动程序需要对其进行相关配置,本文以VS2008和WDK7600为例,讲解了实现编译驱动程序的配置方法。一、安装VS2008和WDK7600安装路径为默认路径,即VS2008的安装路径为C:\ProgramFile...

Linux驱动程序之NOR FLASH

01-12

驱动框架入门之LED-linux驱动开发第4部分

10-18

字符设备驱动基础-linux驱动开发第2部分

10-18

Linux 声卡驱动程序

01-12

u011734144的专栏

04-10 8710

Windows7下VS2013+WDK8.1开发WDF驱动程序全过程

1.安装软件下载安装VS2013+WDK8.1软件,安装完成后两个软件会自动整合到一起,不需要额外的配置。2.开发WDF驱动打开VS2013,“文件”-“新建“-”项目“,在左边选择VisualC++下的WindowsDriver,选择WDF,然后选择KernelModeDriver(KMDF)VisualC++,输入你要创建的驱动的名称,点击“确定”就创建了一个KM......

一只奋斗的菜鸟的专栏

03-01 2274

驱动程序开发的步骤

1、建立Linux驱动骨架(装载和卸载Linux驱动)    装载卸载  module_init和moudle_exit宏指定。    装载时进行初始化,如:建立设备文件,分配内存地址空间    卸载时进行释放驱动占用的资源,如:射出设备文件,释放内存地址空间2、注册和注销设备文件    建立设备文件一般在第一步编写的处理Linux初始化工作的函数中完成。    删除设备文...

Linux驱动开发培训系列教程

11-21

enjoy5512的博客

07-05 7978

Windows驱动开发之第一个驱动程序

一个简单的驱动程序

韦东山嵌入式Linux第一期视频

11-29

aaaaatiger--寻路

04-07 3369

驱动程序开发

摘要第一章 绪论驱动程序实际上可以理解为是一系列控制硬件设备的函数。在DOS系统中,一个驱动程序可能是一个连到应用程序.EXE中的一个模块或者是与应用程序分开的一个独立部分;在Widows系统中,封装驱动程序的方法是制作一个DLL或VxD。在早期,由于我们一般涉及的与计算机相关的硬件设备都是标准设备,它们的驱动程序是由厂家或专门的程序开发人员提供并加以封装,用户只需了解与驱动程序相连的Window...

qq_36535153的博客

08-12 6323

VS2019 windows驱动开发环境配置

配置Windows驱动开发环境VS2019下载VS2019下载链接https://visualstudio.microsoft.com/zh-hans/downloads/选择你所需要的开发环境和配置确认下载完后,在你安装的WDK的文件夹下选择双击WDK.vsix按照提示进行点击,便可将驱动模板加载进vs2019中选择KMDF即可创建驱动项目编译也没问题......

8D Spaces

01-26 3643

VxWorks驱动程序开发指南(四)--驱动程序的组织结构

驱动程序的组织结构驱动程序最重要的部分就是驱动程序源代码文件,源文件描述了设备如何和VxBus、VxWorks OS交互。但是,VxWorks 设备驱动程序还需要另外一些文件,这些附加文件能够帮助你将自己编写的驱动集成到VxWorks编译环境中去,这也是发布驱动程序最重要的一步。本节主要讨论如何在源码树中找到相关的驱动程序文件和其他附加文件。最后还说明驱动程序的各个部分是如何安装在VxWork...
©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客 返回首页

你可能感兴趣的:(VS2008 开发驱动程序)