启动时要创建两个工作线程一个用于发数据一个用于收数据。
发数据线程是我们主动控制不发送数据的时候可以通过WaitorMultiplebjects让线程挂起有数据需要发送的时候在SetEvent让线程恢复发送完数据后继续挂起。
关键的问题点是如何适当地控制收线程没有数据的时候如何挂起如果收数据过程中出错又该如何处理先用Peid发现软件用VC编写并且没有加壳因此先用W32dasm静态反汇编参考的USB通信程序然后用llydbg加载EXE文件对Createile下断点跟踪收线程的处理通过不断地单步跟踪分析发现采用的模式类似于网络编程中重叠模型有两个值得注意的地方是事件注册和缓冲区大小关键反汇编代码部分代码如下calldwordptrKERNEL32ReadileKERNEL32Readile……calldwordptrKERNEL32etLastErrKERNEL32etLastError……push28注册40个事件calldwordptrKRNL32WaitForulKERNEL32WaitForultiplebjectscmpeax28判断具体那个事件触发……calldwordptrKERNEL32etverlapKERNEL32etverlappedResult……push1000缓冲区大小如果改变会导致没有事件触发估计与W驱动有关calldwordptrKRNL32ReadFileKRNL32ReadFile……calldwordptrKRNL32etLastrrKRNL32etLastrror通过前面的分析基本上了解了通信的方式接下来看此USB通信程序的出错处理方法是突然拨出USB设备此时ReadFile返回值必然报错然后继续单步跟踪分析程序发现处理方法是关闭USB设备句柄然后回到查找设备等待找到设备后再次注册时间采用重叠I0模型来收发数据。
22VC模拟实现USB通信程序1内存池类的编写。
思路是将每次数据定义为包程序启动时分配很多这样的包收到数据后就分配一个未使用的并将标志位置成已使用使用完毕后再置成未使用分配前需要判断次包的缓冲区长度是否足够如果所有已申请的包长度不够这需要自动增加包的数量另外也要自动减少包的数量保持在一个平衡的位置因此首先定义一个包类CPackagesgUL类图如图2所示。
接下来定义一个CemPool类给出了类中的关键参数UL类图如图3所示。
外部只需要调用InitemPool、Allocem、Releaseem就可以实现内存池分配和释放。
当Allocem的参数wSize大于所有的内存池中的包此时会自动调用AddemPool增加内存池另外在适当的时候要减少内存池保持一种平衡。
2通信类的编写。
通信类的主要思想是在程序初始化的时候分配内存池、初始化重叠I0启动两个工作线程并且将两个线程都挂起发送前恢复发线程然后继续挂起。
收线程在收到数据后会自动恢复并从内存池冲分配一个包将数据拷贝到包的缓冲区处理完毕后通过内存池释放。
因此定义一个CUSBComm类关键参数的UL类图如图4所示。
图2CPackageMsgUML类图图1USB设备查找过程SetupDiGetClassDevs获得一类硬件设备信息SetupDiEnumDeviceInterfaces获得设备信息中的内容结构SetupDiGetDeviceInterfaceDetail获得指定设备接口的详细信息SetupDiDestroyDeviceInfoList销毁设备信息和释放空间查找设备完成YN图3CMemPoolUML类图CPackageMsgm_bUsed:BOOLFALSEm_pDataBuf:BYTENULLm_dwDataLen:DWORD0dwRecvLen:DWORD0IsUsed:BOOLSetUsedFlagBOOLbFlag:voidm_bUsedm_pDataBufm_dwDataLenm_dwRecvLen是否已使用缓冲区指针缓冲区长度数据长度CMemPoolm_pMsgBuf:CPackageMsgNULLm_wCount:DWORD0m_wAddCount:DWORD0m_sect:CRITICAL_SECTION0InitMemPoolWORDwCount:BOOLAllocMemWORDwSize:CPackageMsgReleaseMemCPackagMsgpMsg:voidAddMemPool:BOOLSubMemPool:BOOLm_wCount包的数量m_wAddCount自动增加数量m_sect临界区保护InitMemPool初始化内存池AllocMem内存池分小块内存ReleaseMem内存返换内存池AddMemPool自动增加内存池SubMemPool自动减少内存池80--2012-05-162012-05-162012-05-162012-05-162012-05-162012-05-16第2期值得说明的是在OpenUsb中会先查找设备然后初始化相关信息最后启动线程开始收发数据操作。
当操作出错时先关闭句柄然后重新查找和打开设备。
3结束语以上是反汇编分析过程和VC模拟实现SB通信程序的关键点主要是通过反汇编分析出B设备的GID和所采用的异步方法吸收其中的主要编程思想然后结合自己思路内存池等技术开发了一个高效的基于重叠I模型的多线