USB开发—自上而下(二)

原创 2015年07月09日 17:59:36

上一节已经说明了如何通过InterfaceGUID监测USB设备的状态,本节我们讨论的主题是如何通过设备名称获取通讯上下文的句柄。

应用程序获取设备句柄的一般步骤如下:

#define LIBUSB_DEVICE_NAME "\\\\.\\libusb0-"
bool CDemoMainFrame::OnBtnOpenDevice( void* param )
{ 
     _snprintf(chName, sizeof(chName) - 1,"%s%04d",LIBUSB_DEVICE_NAME, index);
     HANDLE dev = ::CreateFile( chName, 
			0,
			0,
			NULL,
			OPEN_EXISTING,
			FILE_FLAG_OVERLAPPED,
			NULL);
} 
通过格式化获得的字符串为"\\\\.\\libusb0-0",这个名称的来历是什么呢?这还又得回到驱动程序AddDevice说起。AddDevice函数中包含以下操作:

status = IoCreateSymbolicLink(&symbolic_link_name, &nt_device_name);

这里有两个名称,链接名称与设备名称。他们的关系就好比快捷方式与App的关系,设备名称保存于/Device目录,且只能内核本身访问,应用程序访问设备必须通过链接名称,链接名称保存于/DosDevice目录。

这个symbolic_link_name就是我们关注的重点了。在内核驱动中symbolic_link_name的赋值可能是像这样:"\\DosDevices\\libusb0-0",貌似跟上层软件看到的名称有点不太一样!确实,windows系统规定,驱动程序中,链接名称的写法有以下两种:

L"//??//libusb0-0" --->/??/libusb0-0
L"//DosDevices//libusb0-0"--->/DosDevices/libusb0-0

而应用程序中的链接名称写法应该这样:

L"////.//libusb0-0"-->//./libusb0-0

由于C语言规定‘/’前面必须用/做转译字符,所以左边为C语言代码中的写法,右边为实际的链接名称,??是DosDevices的符号链接名;稍后我们会看到,在Iomanager内部系统会自动将//.转换为/??

CreateFile调用成功,返回一个内核对象的句柄Handle,通过句柄就可以实现ReadFile、WriteFile的操作了,CreateFile调用过程如下:

boyzone1

1, 调用ntdll.dll中的Stub函数NtCreateFile,ntdll.dll相当于User到Kernel之间的中转站,而NtCreateFile通过INT指令或SysEnter指令调用系统中的XX号服务,Kernel.exe根据系统调用号选择对应的函数调用,实际上,内核中也有一个NtCreateFile的函数,通过调用号就可以将用户层与内核层的函数联系起来。

2, Kernel层,NtCreateFile通过IoCreateFile实现,IoCreateFile最核心的函数就属ObOpenObjectByName了。通过字面意思,这个函数要做的事情就是通过XX名称打开一个对象,所以需要一个体现对象名称的参数ObjectAttributes,还有访问权限DesiredAccess等作为输入,输出句柄LocalHandle。

3, 个人认为ObpLookupObjectName更名为ObpLookupObjectByName应该更能体现这个函数的真实意图,而且这个函数的可读性很差,绕了半天也没完全弄明白是怎么做的。我只知道在逐节点解析的过程当中,如果碰到了非对象目录,就要调用他自身注册的ParseRoution函数,对于一般的设备对象,这个被注册的函数就是IopParseFile,进入IopParseDevice的地界,就是我们熟悉的操作了,准备一个IRP,通过IoCallDriver调用下层驱动函数,函数返回,Wait信号量。因为我们调用的是CreateFile,所以下层驱动的响应动作也必然是OnMajorCreate。

4, 从ObpLookupObjectName返回之后,还有一个操作也是需要重点注意的:ObpCreateHandle,这个函数输入对象Object,输出Handle句柄,一切看起来都是那么美好,只不过真相总是超出我们的想象。事实上,这里输入的Object并不是我们的设备对象,而是一个文件对象FileObject,通过FileObject->DeviceObject可以访问真正的设备对象,这是操作系统需要操心的问题,我们获取文件对象的句柄Handle就可以实现对设备的读写操作了。


IRP_MJ_CREATE对驱动程序的影响不是很重要,因为这个操作的目的是获取句柄而已,我们调用如下函数,完成这个请求即可...

NTSTATUS complete_irp(IRP *irp, NTSTATUS status, ULONG info)
{
    irp->IoStatus.Status = status;
	irp->IoStatus.Information = info;
	IoCompleteRequest( irp, IO_NO_INCREMENT );
	return status;
}
关于CreateFile的工作过程就先讲到这里,这里留下了很多的疑问没有解决,比如IoParseDevice的工作细节、IoCompleteRequest的工作过程等,因为这两个函数牵扯到的知识点与内容太多了,为了分清主次轻重,后面我准备再起一个专题来说明。


参考资料: 

1, <<Windows内核情景分析>>

2, <<Windows内核原理与实现>>



版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Windows内核学习笔记(四)-- 编写程序手动加载驱动程序

#include #include #include #include #define DRIVER_NAME "HelloDriver"#define DRIVER_PATH "..//...

如何在inf文件中修改pid、vid

Inf文件即Device Information File(设备信息文件),用于引导驱动程序(*.sys)的安装。它实质上是一个文本文件,可以用记事本工具打开查看和编辑。 简单介绍一下USB设备驱动...
  • weijory
  • weijory
  • 2017年07月12日 21:07
  • 380

USB开发—自上而下(四)

聊完了CreateFile的调用过程,我们再来看一看三个非常重要的API函数DeviceIoControl、ReadFile、WriteFile: BOOL WINAPI DeviceIoContro...

USB开发—自上而下(一)

一直都有写技术文章的冲动,无奈自己才疏学浅,文笔太烂,提笔又不知道写什么好,今天终于下定决定,迈出行动的第一步,由于是新手,写的不好不要见怪。 在此之前,假定读者已经准备好一个具有USB通讯的开发板,...

单片机USB—ISP教程

  • 2011年04月27日 00:25
  • 557KB
  • 下载

安装MSP430的LSD-FET430UIF USB仿真器驱动时出错—"INF找不到所需的段落“

转载地址:http://apps.hi.baidu.com/share/detail/22816323 版权归原文作者所有 先前做过实验就发现自己的电脑上出现这款仿真器的INF错误,猜到可能是系统...

VC++源码—USB编程

  • 2011年01月21日 16:25
  • 41KB
  • 下载

Linux设备驱动程序笔记1—USB设备基础

在总结完USB设备操作的具体实现时候,再对《Linux设备驱动程序》的第十三章—USB驱动程序,的内容进行简单总结。这个章节详细描述了Linux的USB设备驱动程序以及USB核心之间的接口信息。 U...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:USB开发—自上而下(二)
举报原因:
原因补充:

(最多只允许输入30个字)