阅读:1429回复:5
版主,你答应的源码(异步读写驱动)还没贴? 劳驾
rt
|
|
最新喜欢:wujiaj... |
沙发#
发布于:2002-06-24 15:21
快帖出来吧,我也想学一学
|
|
|
板凳#
发布于:2002-06-28 05:04
呵呵,这几天忙,没来,见谅见谅。
整个框架结构很简单,但是要实现具体功能就要看你怎么组织这个框架了。你要实现的似乎是个普通的wdm,我手头写好的是个ndis-wdm结构的程序,中间对ndis packet的处理占了一大部分,想来对你也没什么用,针对我以前项目的内容我全部删去,我也懒得大改了,根据你的描述,简单动了动。 //开线程这么开 NTSTATUS StartThread( PUSB_STRUCT TheUsb//你随便吧,我觉得这里给个设备扩展不错 ) { NTSTATUS status; HANDLE hthread; KeInitializeEvent( &(TheUsb->WriteQueueEvent), NotificationEvent, FALSE ); status = PsCreateSystemThread( &hthread, THREAD_ALL_ACCESS, NULL, NULL, NULL, (PKSTART_ROUTINE)WriteThreadRoutine, (PVOID)TheUsb ); if(!NT_SUCCESS(status)) return status; status = ObReferenceObjectByHandle( hthread, THREAD_ALL_ACCESS, NULL, KernelMode, (PVOID*) &TheUsb->WriteThread, NULL ); ZwClose(hthread); return STATUS_SUCCESS; } VOID StopThread( PVOID UsbStru//和上一个给的应该一样,为的就是线程句柄而已,若你选择了一个与众不同的位置,比如把这个句柄放在全局的位置,这里什么都没有也行 ) { PUSB_STRUCT TheUsb=(PUSB_STRUCT)UsbStru; if(TheUsb->WriteThread){ KeWaitForSingleObject( TheUsb->WriteThread, Executive, KernelMode, FALSE, NULL ); ObDereferenceObject(TheUsb->WriteThread); TheUsb->WriteThread=NULL; } } VOID WriteRoutine( PVOID UsbStru//同上 ) { NTSTATUS status; PUSB_STRUCT TheUsb=(PUSB_STRUCT)UsbStru; while(TRUE){ status = KeWaitForSingleObject( &(TheUsb->WriteQueueEvent), Executive, KernelMode, FALSE, NULL ); if(!NT_SUCCESS(status)){//error waiting break; }//error waiting if(TheUsb->ExitWriteThread) break; //这里放实际的调用usb总线驱动发数据的函数,你自己写吧,呵呵, //我的这个函数干的全是和网络层有关的事情,涉及到一些东西,公开了有点对不起我以前的老板:) KeClearEvent(&(TheUsb->WriteQueueEvent)); } //这个线程其实就是死循环,但卸载是没有问题的 PsTerminateSystemThread(STATUS_SUCCESS); } VOID SignalThread( PVOID UsbStru ) { PUSB_STRUCT TheUsb=(PUSB_STRUCT)UsbStru; KeSetEvent(&(TheUsb->WriteQueueEvent),0,FALSE); TheUsb->GoOut=TRUE; } NTSTATUS Mo_USB_DeviceControl(IN PDEVICE_OBJECT fdo,IN PIRP Irp){ ....... //这里你的工作就比较辛苦了,呵呵 //主要工作是入队,不过要做好与自己开的线程的同步 //比较麻烦,我前面贴的4个函数里有几个和event有关的 //都是在做这件事 //首先看看你有没有抢占低优先级发送线程, //然后分情况处理。 PQueuePacket Head =(PQueuePacket)(Adapter->SenPacketsHead); PQueuePacket Tail =(PQueuePacket)(Adapter->SenPacketsTail); PQueuePacket Insert;// = Tail->Next; NDIS_STATUS Status; NdisAcquireSpinLock(&(Adapter->SenSpinLock)); if(!SendInProgress){ //这个中间的代码太多,对你用处似乎不大,所以我删了 //核心思想是直接入队,然后通知线程 }else{//SendInProgress //入队,但不通知线程 } NdisReleaseSpinLock(&(Adapter->SenSpinLock)); ....... } 注:此招对于ndis的某些问题,比如发包时中断级过高有奇效,但对一般wdm程序来说,dispatch例程压根不会在dpc级被调用,所以多少有点於余,你自己组织的时候可以改进一下。 |
|
地板#
发布于:2002-06-28 05:08
贴完了才发现,以前程序组织的很差,哎,真郁闷……
|
|
地下室#
发布于:2002-06-28 08:09
非常感谢wuqix大侠的回答!
很对不起,发贴时忘了给分,在别处给你分. |
|
5楼#
发布于:2002-07-01 12:24
你在异步传输时使用了事件Event,不知你是怎么传进驱动中的。
常用的作法是用DeviceIoCtrl,但实际在WriteFile, ReadFile, DeviceIoControl 中都可以有一个LPOVERLAPPED,但不知在驱动中的IRP中怎么取到这个结构中包含的Event |
|