实战DeviceIoControl 之中的一个:通过API訪问设备驱动程序
Q 在NT/2000/XP中,我想用VC编写应用程序訪问硬件设备,如获取磁盘參数、读写绝对扇区数据、測试光驱实际速度等,该从哪里入手呢?
A 在NT/2000/XP中,应用程序能够通过API函数DeviceIoControl来实现对设备的訪问—获取信息,发送命令,交换数据等。利用该接口函数向指定的设备驱动发送正确的控制码及数据,然后分析它的响应,就能够达到我们的目的。
DeviceIoControl的函数原型为
BOOL DeviceIoControl(HANDLE hDevice, // 设备句柄DWORD dwIoControlCode, // 控制码LPVOID lpInBuffer, // 输入数据缓冲区指针DWORD nInBufferSize, // 输入数据缓冲区长度LPVOID lpOutBuffer, // 输出数据缓冲区指针DWORD nOutBufferSize, // 输出数据缓冲区长度LPDWORD lpBytesReturned, // 输出数据实际长度单元长度LPOVERLAPPED lpOverlapped // 重叠操作结构指针
);
设备句柄用来标识你所訪问的设备。
发送不同的控制码,能够调用设备驱动程序的不同类型的功能。在头文件winioctl.h中,提前定义的标准设备控制码,都以IOCTL或FSCTL开头。比如,IOCTL_DISK_GET_DRIVE_GEOMETRY是对物理驱动器取结构參数(介质类型、柱面数、每柱面磁道数、每磁道扇区数等)的控制码,FSCTL_LOCK_VOLUME是对逻辑驱动器的卷加锁的控制码。
输入输出数据缓冲区是否须要,是何种结构,以及占多少字节空间,全然由不同设备的不同操作类型决定。在头文件winioctl.h中,已经为标准设备提前定义了一些输入输出数据结构。重叠操作结构指针设置为NULL,DeviceIoControl将进行堵塞调用;否则,应在编程时按异步操作设计。
Q 设备句柄是从哪里获得的?
A 设备句柄能够用API函数CreateFile获得。它的原型为
HANDLE CreateFile(LPCTSTR lpFileName, // 文件名称/设备路径DWORD dwDesiredAccess, // 訪问方式DWORD dwShareMode, // 共享方式LPSECURITY_ATTRIBUTES lpSecurityAttributes, // 安全描写叙述符指针DWORD dwCreationDisposition, // 创建方式DWORD dwFlagsAndAttributes, // 文件属性及标志HANDLE hTemplateFile // 模板文件的句柄
);
CreateFile这个函数用处非常多,这里我们用它“打开”设备驱动程序,得到设备的句柄。操作完毕后用CloseHandle关闭设备句柄。
与普通文件名称有所不同,设备驱动的“文件名称”(常称为“设备路径”)形式固定为“//./DeviceName”(注意在C程序中该字符串写法为“.//DeviceName”),DeviceName必须与设备驱动程序内定义的设备名称一致。
一般地,调用CreateFile获得设备句柄时,訪问方式參数设置为0或GENERIC_READ|GENERIC_WRITE,共享方式參数设置为FILE_SHARE_READ|FILE_SHARE_WRITE,创建方式參数设置为OPEN_EXISTING,其他參数设置为0或NULL。
Q 但是,我怎么知道设备名称是什么呢?
A 一些存储设备的名称是微软定义好的,不可能有什么变化。大体列出例如以下
软盘驱动器 | A:, B: |
硬盘逻辑分区 | C:, D:, E:, ... |
物理驱动器 | PHYSICALDRIVEx |
CD-ROM, DVD/ROM | CDROMx |
磁带机 | TAPEx |
当中,物理驱动器不包含软驱和光驱。逻辑驱动器能够是IDE/SCSI/PCMCIA/USB接口的硬盘分区(卷)、光驱、MO、CF卡等,甚至是虚拟盘。x=0,1,2 ……
其他的设备名称需通过驱动接口的GUID调用设备管理函数族取得,这里暂不讨论。
Q 请举一个简单的样例说明怎样通过DeviceIoControl訪问设备驱动程序。
A 这里有一个从MSDN上摘抄来的demo程序,演示在NT/2000/XP中怎样通过DeviceIoControl获取硬盘的基本參数。
/* The code of interest is in the subroutine GetDriveGeometry. Thecode in main shows how to interpret the results of the IOCTL call. */#include <windows.h>
#include <winioctl.h>BOOL GetDriveGeometry(DISK_GEOMETRY *pdg)
{HANDLE hDevice; // handle to the drive to be examinedBOOL bResult; // results flagDWORD junk; // discard resultshDevice = CreateFile(".//PhysicalDrive0", // drive to open0, // no access to the driveFILE_SHARE_READ | // share modeFILE_SHARE_WRITE,NULL, // default security attributesOPEN_EXISTING, // disposition0, // file attributesNULL); // do not copy file attributesif (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive{return (FALSE);}bResult = DeviceIoControl(hDevice, // device to be queriedIOCTL_DISK_GET_DRIVE_GEOMETRY, // operation to performNULL, 0, // no input bufferpdg, sizeof(*pdg), // output buffer&junk, // # bytes returned(LPOVERLAPPED) NULL); // synchronous I/OCloseHandle(hDevice);return (bResult);
}int main(int argc, char *argv[])
{DISK_GEOMETRY pdg; // disk drive geometry structureBOOL bResult; // generic results flagULONGLONG DiskSize; // size of the drive, in bytesbResult = GetDriveGeometry (&pdg);if (bResult){printf("Cylinders = %I64d/n", pdg.Cylinders);printf("Tracks per cylinder = %ld/n", (ULONG) pdg.TracksPerCylinder);printf("Sectors per track = %ld/n", (ULONG) pdg.SectorsPerTrack);printf("Bytes per sector = %ld/n", (ULONG) pdg.BytesPerSector);DiskSize = pdg.Cylinders.QuadPart * (ULONG)pdg.TracksPerCylinder *(ULONG)pdg.SectorsPerTrack * (ULONG)pdg.BytesPerSector;printf("Disk size = %I64d (Bytes) = %I64d (Mb)/n", DiskSize,DiskSize / (1024 * 1024));}else{printf("GetDriveGeometry failed. Error %ld./n", GetLastError());}return ((int)bResult);
}
Q 假设将设备名换成“A:”就能够取A盘參数,换成“CDROM0”就能够取CDROM參数,是这样吗?
A 这个问题暂不做回答。请动手试一下。
如今我们总结一下通过DeviceIoControl訪问设备驱动程序的“三步曲”:首先用CreateFile取得设备句柄,然后用DeviceIoControl与设备进行I/O,最后别忘记用CloseHandle关闭设备句柄。
[相关资源]
bhw98的专栏:http://www.csdn.net/develop/author/netauthor/bhw98/
首次公布:2003-02-16
最后修订:2003-05-20
实战DeviceIoControl 之中的一个:通过API訪问设备驱动程序相关推荐
- 实验六 实现一个基于内存映射的设备驱动程序
实验六 实现一个基于内存映射的设备驱动程序 目录 实验六 实现一个基于内存映射的设备驱动程序 实验环境 一.实验目的 二.实验内容 三.实验步骤 四.实验总结 实验环境 操作系统版本:ubuntu-1 ...
- HDFS简单介绍及用C语言訪问HDFS接口操作实践
一.概述 近年来,大数据技术如火如荼,怎样存储海量数据也成了当今的热点和难点问题,而HDFS分布式文件系统作为Hadoop项目的分布式存储基础,也为HBASE提供数据持久化功能,它在大数据项目中有很广 ...
- Nginx 訪问日志增长暴增出现尖刀的具体分析
前言: Nginx日志里面Mobileweb_access.log增长特别大.一天上百兆.将近100W的訪问记录.依照我们眼下的规模,热点用户才500个左右.就算人人用手机app訪问 ...
- 写一个块设备驱动程序
----------------------- Page 1----------------------- 第 1章 +---------------------------------------- ...
- SoC嵌入式软件架构设计之中的一个:系统内存需求评估
内存是SoC(System on Chip,片上系统)集成设计的重要模块.是SoC中成本比重较大的部分.内存管理的软硬件设计是SoC软件架构设计的重要一环,架构设计师必需要在成本和效率中取得平衡,做到 ...
- 【浅墨Unity3D Shader编程】之中的一个 夏威夷篇:游戏场景的创建 amp; 第一个Shader的书写...
本系列文章由@浅墨_毛星云 出品.转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/40723789 作者:毛星云(浅墨) ...
- 【微信测试号实战——01】注册一个属于你自己的微信测试号
系列文章目录 微信测试号系列文章,快速进入 [微信测试号实战--01]注册一个属于你自己的微信测试号 文章目录 系列文章目录 前言 一.打开微信测试号官网 二.使用步骤 1.打开手机端微信 2.扫码登 ...
- MFC: DeviceIoControl 通过API访问设备驱动程序
转载:http://m.blog.csdn.net/article/details?id=21602051 DeviceIoControl的其实和ReadFile和WriteFile是一样的, 不过这 ...
- 【Android开发VR实战】三.开发一个寻宝类VR游戏TreasureHunt
转载请注明出处:http://blog.csdn.net/linglongxin24/article/details/53939303 本文出自[DylanAndroid的博客] [Android开发 ...
最新文章
- ARM 环境下使用azure powershell 从远程blob中拉去vhd 并创建虚拟机
- oracle11g快速入门习题集答案——oracle11g快速入门
- 播放失败246106异常代码_web前端面试题:您能读懂的Promise源码实现(手写代码)...
- 前端传值后端接收不到_web前端和后端哪个好
- mysql 的 VARCHAR VARCHAR2
- 学妹靠这个学会硬件开发入职华为,今天搞到100个免费名额!
- 公司项目拓扑的演变过程
- AOP的实现方式比较,cglib vs jdk
- 签约沈腾,易车开启三年品牌计划,穿越车市寒冬
- Android 开发之ViewPage官方文档学习笔记
- [Java] 蓝桥杯ADV-203 算法提高 8皇后·改
- [导入]js 关联数组 详解
- linux不同主机通信,Linux实现多台主机之间相互通信
- 【JAVA程序设计】(C00075)基于SSM的网上汽车租赁管理系统
- ps4插html屏幕不亮光,ps4连接显示器怎么老是黑屏
- Layabox 实现 PageView 翻页
- Java串口编程控制硬件
- 如何用 React 完成图片上传功能
- 分析mrp主要应用范围_MRP适用于相关需求的计划与控制
- 学习-Python列表之列表应用之降序排列
热门文章
- Linux下使用终端调试Python程序:pudb
- 户外lisp导向牌如何安装_有了激光切割导向牌,妈妈再也不用担心我迷路啦
- java实现随机字母数字验证码
- SpringBoot集成websocket(Spring方式)
- Nginx的location、root、alias指令用法和区别
- c 读取mysql中表中数据_c#读取MySQL数据表中的内容
- php连接不到mysql怎么解决,怎么解决php无法连接mysql的问题
- python中dom是什么意思_python--BOM和DOM
- shell脚本教学进阶——Linux三大文本处理工具之grep
- c语言逆序输出字符串指针,菜鸟求助-如何用指针法将一串字符按单词的倒序输出?如:i love yo...