`
isiqi
  • 浏览: 16004067 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

[DEV] 虚拟设备驱动程序的设计与实现

阅读更多
虚拟设备驱动程序的设计与实现
  由于Windows对系统底层操作采取了屏蔽的策略,因而对用户而言,系统变得更为安全,但这却给众多的硬件或者系统软件开发人员带来了不小的困难,因为只要应用中涉及到底层的操作,开发人员就不得不深入到Windows的内核去编写属于系统级的虚拟设备驱动程序。Win98与Win 95设备驱动程序的机理不尽相同,Win 98不仅支持与Windows NT 5.0兼容的WDM(Win32 DriverMode)模式驱动程序,而且还支持与Win 95兼容的虚拟设备驱动程序VxD(Virtual DeviceDriver)。下面介绍了基于Windows9x平台的虚拟环境、虚拟设备驱动程序VxD的基本原理和设计方法,并结合开发工具VToolsD给出了一个为可视电话音频卡配套的虚拟设备驱动程序VxD的设计实例。

  1.Windows 9x的虚拟环境
  Windows 9x作为一个完整的32位多任务操作系统,它不像Window
3.x那样依赖于MS-DOS,但为了保证软件的兼容性,Windows
9x除了支持Win16应用程序和Win32应用程序之外,还得支持MS-DOS应用程序的运行。Windows 9x是通过虚拟机VM(Virtual
Machine)环境来确保其兼容和多任务特性的。
  所谓Windows虚拟机(通常简称为Windows
VM)就是指执行应用程序的虚拟环境,它包括MS-DOS VM和System VM两种虚拟机环境。在每一个MS-DOS
VM中都只运行一个MS-DOS进程,而System VM能为所有的Windows应用程序和动态链接库DLL(Dynamic Link
Libraries)提供运行环境。每个虚拟机都有独立的地址空间、寄存器状态、堆栈、局部描述符表、中断表状态和执行优先权。虽然Win16、Win32应用程序都运行在System
VM环境下,但Win16应用程序共享同一地址空间,而Win32应用程序却有自己独立的地址空间。

  在编写应用程序时,编程人员经常忽略虚拟环境和实环境之间的差异,一般认为虚拟环境也就是实环境。但是,在编写虚拟设备驱动程序VxD时却不能这样做,因为VxD的工作是向应用程序代码提供一个与硬件接口的环境,为每一个客户虚拟机管理虚设备的状态,透明地仲裁多个应用程序,同时对底层硬件进行访问。这就是所谓虚拟化的概念。

  VxD在虚拟机管理器VMM(Virtual Machine
Manager)的监控下运行,而VMM实际上是一个特殊的VxD。VMM执行与系统资源有关的工作,提供虚拟机环境(能产生、调度、卸载VM)、负责调度多线程占先时间片及管理虚拟内存等工作。VxD与VMM运行在其他任何虚拟机之外,VxD事实上就是实现虚拟机的软件的一部分。

  与大多数操作系统一样,Windows也是采用层次式体系结构。VMM和VxDs构成了Win
95的ring0级的系统核心(应用程序运行在ring3级,ring1、ring2级未被使用),具有系统的最高优先权。Windows还提供一些以"drv"为后缀名的驱动程序,主要是指串行口的通信程序和并行口的打印机程序。这些程序与VxD不同,它们是运行在ring3级上的。图1可以使你更好地理解Windows的虚拟环境。

  图
  2.深入理解VMM和VxD
  如前所述,VxD是Virtual Device
Driver的缩写,但有人将它理解为虚拟任何驱动程序。实际上,VxD并非仅指那些虚拟化的某一具体硬件的设备驱动程序。比如某些VxD能够虚拟化设备,而某些VxD作为设备驱动程序却并不虚拟化设备,还有些VxD与设备并没有什么关系,它仅向其他的VxD或是应用程序提供服务。

  VxD可以随VMM一起静态加载,也可以根据需要动态加载或卸载。正是由于VxD与VMM之间的紧密协作,才使得VxD具有了应用程序所不具备的能力,诸如可以不受限制地访问硬件设备、任意查看操作系统数据结构(如描述符表、页表等)、访问任何内存区域、捕获软件中断、捕获I/O端口操作和内存访问等,甚至还可以截取硬件中断。

  尽管VxD使用32位平面存储模式(flat memory
model),但它的代码和数据仍使用分段管理,段有六种类型,即实模式初始化、保护模式初始化、可分页、不可分页、静态和只调试(debug
only),每种类型又有代码段和数据段之分,所以VxD共有12个段。实模式代码段和数据段为16位(分段模式),其他段则是32位(平面模式)。“实模式初始化”段包含了在Windows初始化过程的最初阶段VMM变为保护模式之前要执行的代码。静态加载的VxD此时可以查看Windows启动前的实模式环境,决定是否继续加载,并通知VMM。加载完毕后,VMM进入保护模式并执行保护模式初始化代码,同样将执行结果再通知VMM。初始化完成后,“实模式初始化”段和“保护模式初始化”段即被遗弃。VxD的大部分代码都在其他的某一段中,“可分页”段允许虚拟存储管理器(Virtual
Memory
Manager)进行分页管理,大多数的VxD代码都应当在“可分页”段。“不可分页”段的内容主要包括:VxD的主入口点、硬件中断处理函数、所访问的数据以及能被另一个VxD中断处理函数调用的异步服务。“静态”段仅用于可以动态加载的VxD,当VxD卸载后,静态代码段和数据段都保留在内存中。“只调试”段只是VMM在Soft-ICE
for Win 95等调试环境下才将其载入。
  VMM是通过VxD的设备描述符块DDB(Device Descriptor
Block)来识别的。DDB向VMM提供了VxD的主入口点,还向应用程序和其他的VxD提供了入口点。VMM利用这个主入口点将VM及Windows自身的状态通知给VxD,然后VxD通过相应的工作来响应这些事件。由于VxD不仅仅服务于一个物理设备(比如多个串口)或仅与一个VM发生联系,所以VxD需要产生自己支持的数据结构(Supporting
Data
Structures)来保存每一个设备、每一个VM的配置和状态信息。VxD用一个或多个设备上下文结构来保存设备信息,如I/O端口基地址、中断向量等,VxD将自己的每个VM的状态信息保存在VMM的VM控制块中。

  VMM提供的服务包括:事件服务、内存管理服务、兼容执行和保护模式执行的服务、登录表服务、调度程序服务、同步服务、调试服务、I/O捕获服务、处理错误和中断服务、VM中断和回调服务、配置管理程序服务以及其他杂项服务。

  以上内容仅涉及到VxD设计的一小部分,作为VxD的开发人员必须掌握更多的知识。首先是操作系统的知识,如地址空间、执行上下文、资源加锁、进程间通信和异步事件处理等方面的知识;其次,对Intel处理器应有较深入的理解,包括寄存器、机器指令集、保护机制、分页机制,以及虚拟8086模式;最后,还必须熟悉VMM提供的各类服务和接口,熟悉Windows其他的系统VxD。

  3.开发工具VToolsD简介

  VToolsD是专门用于开发VxD程序的一种工具软件,它包括VxD框架代码生成器QuickVxD、C运行库、VMM/VxD服务库、VxD的C++类库、VxDLoad和VxDView等实用工具以及大量的C、C++例程。由VC++、BC++的32位编译器编译生成的VxD程序可以脱离VToolsD环境运行。

  利用QuickVxD可以方便、快捷地生成VxD的框架,即生成后缀名为h、cpp和mak的三个文件。源文件包含了运行VxD的基本组件,其中包含控制消息处理、API入口点、以及VxD服务等函数框架,并且还定义了标志,设置了编译参数,声明了类,然后在C++环境下,向生成的各个处理函数体内添加自己的代码,最后使用编译器NMAKE生成标准的VxD程序。

  由于VxD运行在ring0级,所以调试程序相当困难。我使用的调试工具是Soft-ICE for Win 95。

  目前VToolsD的最新版本为3.0,它支持设备访问体系结构DAA(Device Access
Architecture),所编写的程序代码将可以在所有Windows平台(包括Win 95、Win 98以及Windows
NT)上共享。当然也可以使用Microsoft公司的DDK(Device Developer
Kit)来开发VxD,但DDK不能像VToolsD那样通过屏蔽系统及VxD的底层技术细节提供丰富的C运行库和C++类库,而是让开发人员充分享用面向对象编程方法的方便与快捷,因此仅就该点而言,使用DDK是不方便的。

  4.VxD程序设计实例
  我在开发可视电话音频卡的设计过程中,用VToolsD 2.03、VC++
5.0为自制的PC/XT总线扩展卡开发了虚拟设备驱动程序Audcard.vxd。该卡每20ms申请一次中断,中断由应用程序动态载入系统的Audcard.vxd响应并加以处理。中断服务程序ISR(Interrupt
Service Routine)结束后,调用函数Shell_PostMessage(
)向应用程序窗口发送自定义消息。应用程序接受消息后,再通过函数DeviceIoControl(
)与VxD的接口函数OnW32DeviceIoControl( )互传缓冲区数据。程序结束即可动态卸载VxD。下图表示在Win
95下VxD对硬件中断的处理过程。
  图Win95下硬件中断的处理过程

  当中断发生时,处理器转换为ring0级保护模式。Windows系统并不像DOS那样通过中断描述符表IDT(Interrupt
Descriptor
Table)直接指向中断处理过程,而是由IDT入口指向VMM中的程序。该程序将判断是否为中断调用,如果是,则把中断控制权交给虚拟可编程中断控制器VPICD(Virtual
Programmable Interrupt Controller
Device),VPICD实际上是一个重要的VxD。VPICD再将其交给另一个注册了该中断的VxD(如Audcard.vxd)来处理。VxD程序是通过调用VPICD服务VPICD_Virtualize_IRQ来注册中断的。

  虚拟设备驱动程序Audcard.vxd的部分源代码Audcard.h和Audcard.cpp在网上,网址为:www.pccomputing.com.cn。此应用程序使用了下列函数:CreateFile()动态加载VxD、CloseHandle()并动态卸载VxD、PreTranslateMessage()截获消息、DeviceIoControl()与VxD互传缓冲区数据。虚拟设备驱动程序Audcard.vxd经调试后工作正常,未发生过任何丢失数据或死机的现象。

  下面是虚拟设备驱动程序Audcard.vxd的部分源代码Audcard.h和Audcard.cpp,限于篇幅,由QuickVxD自动生成的Audcard.mak未列出。

  ①Audcard.h
  //AUDCARD.h - include file for VxD AUDCARD

  #include
  #define DEVICE_CLASS AudcardDevice
  #define
AUDCARD_DeviceID UNDEFINED_DEVICE_ID
  #define AUDCARD_Init_Order
UNDEFINED_INIT_ORDER#define AUDCARD_Major
  #define AUDCARD_Minor 0

  #define MY_IRQ 5 //定义5号中断
  class MyHwInt:public VHardwareInt

  {
  public:
   MyHwInt():VHardwareInt(MY_IRQ,0,0,0){}
  
virtual VOID OnHardwareInt(VMHANDLE);
  };
  class AudcardDevice :
public VDevice
  {
  public:
   virtual BOOL
OnSysDynamicDeviceInit();
   virtual BOOL OnSysDynamicDeviceExit();

   virtual DWORD OnW32DeviceIoControl(PIOCTLPARAMS pDIOCParams);

   MyHwInt* pMyIRQ;
  };
  class AudcardVM : public
VVirtualMachine
  {
  public:
   AudcardVM(VMHANDLE hVM);

  };
  class AudcardThread : public VThread
  {
   public:

   AudcardThread(THREADHANDLE hThread);
  };
  

  ②Audcard.cpp
  //AUDCARD.cpp - main module for VxD AUDCARD

  #define DEVICE_MAIN
  #include "audcard.h"

  Declare_Virtual_Device(AUDCARD)
  #define WM_USER_POSTVXD
0x1000
  //自定义消息
  #undef DEVICE_MAIN

  AudcardVM::AudcardVM(VMHANDLE hVM) : VVirtualMachine(hVM) {}

  AudcardThread::AudcardThread(THREADHANDLE hThread) :
VThread(hThread) {}
  BOOL AudcardDevice::OnSysDynamicDeviceInit()
//动态加载时初始化
  {
   ......//硬件初始化
   pMyIRQ=new MyHwInt();

  if(pMyIRQ&&pMyIRQ->hook()) //挂接中断
  {
  
pMyIRQ->physicalUnmask(); //允许中断
   return TRUE;
   }
  
else return FALSE;
  }
  BOOL
AudcardDevice::OnSysDynamicDeviceExit()
  //动态卸载过程
  {
  
delete pMyIRQ;
   return TRUE;
  }
  DWORD
AudcardDevice::OnW32DeviceIoControl(PIOCTLPARAMS pDIOCParams)

  //与Win32应用程序的接口函数
  {
  ......
  }
  VOID
MyHwInt::OnHardwareInt(VMHANDLE hVM)
  {
   ...... // 中断处理
  
SHELL_PostMessage(AppWnd,WM_USER_POSTVXD ,0,0,0,NULL);
  
//向应用程序窗口发送消息
   sendPhysicalEOI(); //通知VPICD中断结束
  }
分享到:
评论

相关推荐

    linux字符设备驱动实例

    一个虚拟的linux字符设备驱动实例,包括对/sys, 及/dev下设备文件的自动生成

    虚拟驱动模拟实验

    验要求:1、使用内存模拟字符设备,实现读、写、定位的字符设备驱动程序; 2、编写应用程序、测试驱动; 实验器材: 软件:安装fedora8的系统; 硬件:PC机一台。 设计过程: 1、编写驱动程序memdev.c,实现读、写...

    linux 添加字符设备驱动程序及测试程序.zip

    linux 添加字符设备驱动程序及测试程序,linux下采用模块方法,添加一个新的设备驱动程序。要求添加字符设备的驱动。另附一个应用程序,测试添加的驱动程序. int main(void) { int fd; char buf[MAX_SIZE]; char ...

    联想虚拟电源控制器驱动

    联想的虚拟电源控制器驱动。 设备描述:Lenovo ACPI-Compliant Virtual Power 实例路径:ACPI\VPC2004\0 硬件ID:ACPI\VEN_VPC&DEV_2004 驱动日期:2009/10/19 驱动版本:5.4.0.1 物理设备:\Device\0000002a

    基于C语言实现的一个虚拟串口驱动程序,加载驱动后会产生两个软件模拟的串口ttyVIRT设备驱动,可以互相通讯

    这是一个软件模拟的串口ttyVIRT设备驱动,加载驱动后,会产生/dev/ttyVIRT0和/dev/ttyVIRT1两个设备,不同的应用程序分别打开这两个串口设备可以互相通信。 安装 make make load 卸载 make unload

    编写设备驱动程序

    设备驱动程序设计注意事项 ........................................................................................................... 46 DDI/DKI功能 .......................................................

    针对Linux的FTDI驱动程序安装指南

    FTDI对所有受支持的操作系统都有两种类型的驱动程序。这些分别是虚拟COM端口...为了确保所有FTDI设备都有VCP驱动程序支持,FTDI建议在Linux系统上安装最新的内核版本。在Linux中,VCP驱动程序将显示为/dev/ttyUSBx。

    vcdev:虚拟V4L2设备Linux内核驱动程序

    虚拟V4L2 Linux内核驱动程序 作者:Jan Sebechlebsky 该模块使用proc文件中的原始输入实现简单的虚拟摄像头设备。 该驱动程序具有很高的实验性,使用风险自负。 建筑模块 在克隆存储库的根目录中运行make之后,应...

    xen环境下前后端虚拟驱动 demo代码

    在xen环境下domain0与domainU之间虚拟驱动样例代码;使用方法如下: 1)在domain0中编译domain0代码 并使用insmod命令进行安装驱动 2)在domainU中编译domainU代码以及应用app 3)在domainU中insmod安装domainU驱动 4)...

    linux虚拟磁盘源代码

    1. 使用insmod加载驱动程序。rmod卸载驱动程序。 dmesg |tail -20查看最后的内核调试信息输出。 2. 加载成功后,可在/dev目录下,看到加载的设备myramblock.使用 mkdosfs /dev/myramblock,初始化虚拟磁盘。 3. 把...

    Linux平台设备驱动模型

    平台总线(Platform bus)是linux2.6内核加入的一种虚拟总线,其优势在于采用了总线的模型对设备与驱动进行了管理,这样提高了程序的可移植性  2.  二、平台设备  1. 平台设备使用structplatform_device来描述:...

    s390-tools:与s390 Linux内核和设备驱动程序一起使用的工具

    s390-tools软件包包含一组与s390 Linux内核和设备驱动程序一起使用的用户空间实用程序的源树。 该软件包还包含以下文件: :贡献准则 :适用于此软件包的MIT许可证 :s390工具版本的历史 :s390-tools软件包的...

    linux 驱动编写之虚拟字符设备的编写实例详解

    linux 驱动编写 前言:  昨天我们说了一些简单模块编写方法,但是终归没有涉及到设备的编写内容,今天我们就可以了解... (1)我真的搞懂设备的开发驱动流程了吗?我是否可以从0开始,编写一个独立的驱动代码呢?  

    platform总线下的简单驱动

    my_dev.c是设备文件,my_dri.c是驱动文件,使用echo可以对驱动进行调试。

    UNIX 高级教程系统技术内幕

    第16 章 设备驱动程序I/O(446) 16.1 简介 16.2 概述 16.2.1 硬件配置 16.2.2 设备中断 16.3 设备驱动程序框架 16.3.1 设备和驱动程序分类 16.3.2 调用驱动程序代码 16.3.3 设备开关表 16.3.4 驱动程序入口点 16.4 I/...

    unix分析关于UNIX的一些浅析

    事实上,在向总线注册设备时,同样会进行类似的操作,遍历总线上所有驱动程序,找到则进行设备与驱动程序的绑定。 static int __driver_attach(struct device *dev, void *data) { struct device_driver *drv = ...

    DevCon 实用工具是一种命令行实用工具,可以替代设备管理器(禁用启用重启网卡的方法)

     stack 列出预期的设备驱动程序堆栈。  status 列出设备的运行状态。  update 手动更新设备。  UpdateNI 手动更新设备,无用户提示  SetHwID 添加、删除和更改根枚举设备的硬件 ID 的顺序。 示例:  ...

    bmi160调通bmi160的ACC+GYR_20160907.7z

    2、将驱动程序bma250.c中的bma250全部替换为bmi160,验证是可以加入新的gsensor的(陀螺仪类似)。 3、借用bma250.c这个驱动程序,初始化的部分修改为初始化bmi160,调通BMI160的gsensor部分。 4、完善全志/博世提供...

    drivers_实验资料\kernel课程\内核课程.chm

    Drivers:这个目录是内核中最庞大的一个目录,显卡、网卡、SCSI适配器、PCI总线、USB总线和其他任何Linux支持的外围设备或总线的驱动程序都可以在这里找到,驱动一般分成字符设备和块设备,但是现在内核把驱动做成了...

    velleman-K8055-开源

    该项目为Velleman K8055 USB实验接口板提供了一个Linux内核模块驱动程序。 它创建并允许您访问/ dev / k8055虚拟设备文件。 您可以通过c程序通过ioctl()与驱动程序进行通信。 祝您黑客愉快!

Global site tag (gtag.js) - Google Analytics