SlavaI
Главный специалист
Offline
|
|
« Ответ #1 : 24-09-2003 07:37 » |
|
Да все просто. Если нужна абсолютная независимость чтения/записи(то есть дуплекс) то делай два потока(если один поток то будет полудуплекс), каждый из котрых ждет на событии, в драйвере помещаешь IRP в очередь, для чего можешь сделать простенькую структурку
struct Irp_Container { LIST_ENTRY ListEntry; PIRP Irp; };
создаешь два события
KEVENT global_ReadEvent; KEVENT global_WriteEvent;
инициализируешь их до первого использования
KeInitializeEvent(&global_ReadEvent,SynchronizationEvent,FALSE); KeInitializeEvent(&global_WriteEvent,SynchronizationEvent,FALSE);
создаешь заголовки двух очередей
LIST_ENTRY global_read_list; LIST_ENTRY global_write_list;
также инициализируешь до первого использования
InitializeListHead(&global_read_list); InitializeListHead(&global_write_list);
создаешь спин блокировки для блокирования доступа к спискам
KSPIN_LOCK global_SpinLockRead; KSPIN_LOCK global_SpinLockWrite;
также инициализируешь до первого использования
KeInitializeSpinLock(&global_SpinLockRead); KeInitializeSpinLock(&global_SpinLockWrite);
Делаешь ф-ции потоков(показываю только одну)
VOID ReadIrpThread (IN PVOID Context) { PLIST_ENTRY request; PIRP pIrp; Irp_Container* pReadIrp ; KeSetPriorityThread(KeGetCurrentThread(),LOW_REALTIME_PRIORITY); while (TRUE) { KeWaitForSingleObject(&global_ReadEvent,Executive,KernelMode,FALSE,NULL); while (request = ExInterlockedRemoveHeadList(&global_read_list,&global_SpinLockRead)) { pReadIrp= CONTAINING_RECORD(request,Irp_Container,ListEntry); pIrp = pReadIrp->Irp; ................................................... тут обрабатываешь Irp } if (InterlockedCompareExchange(&global_TerminateReadThread,0,0)) { dprintf("Terminating Thread\n"); PsTerminateSystemThread(STATUS_SUCCESS); }
}
}
в драйвере помещаешь IRP в очередь и савишь event в сигнальное состояние, поток проснется и вынет его из очереди и обработает. Память под структуру Irp_Container выделяй из неподкачиваемого пула и не забывай освобождать после того как из очереди в потоке обработки вынешь. Вот как помещать в очередь
Irp_Container* pIrpContainer; pIrpContainer = ExAllocatePool(NonPagedPool,....); pIrpContainer->Irp=Irp;
ExInterlockedInsertTailList(&global_read_list,&pIrpContainer->ListEntry,&global_SpinLockRead); // Sending Event to ReadIrpThread KeSetEvent(&g_AccessThreadEvent,(KPRIORITY)0,FALSE);
Для остановки потока ставишь переменную global_TerminateReadThread в и 1 переводишь событие в сигнальное состояние. Потоки создаешь при помощи PsCreateSystemThread. Продумай, что ты будешь делать после откладывания IRP на обработку- возваращать STATUS_PENDING или блокировать и ждать обработки этого IRP. Есть еще системные очереди, но я их не использую. И подумай насколько тебе нужны очереди, может и без них можно?
|