Помогите, пожалуйста, разобраться. Нужно синхронизировать работу дочернего и главного потоков, для этого использую эвенты, и две WaitForSingleObject. Одна из этих функций стоит в обработчике «URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER» запроса(выполняется на уровне dispatch). Трассируя в SoftIce’е обнаружил, что при обработке первого запроса она, как и положено ждет сигнального состояния, но когда ожидание проходит и начинается обработка следующего запроса, на ней при 0 состоянии эвента, почему-то возникает BSOD.
На DISPATCH_LEVEL нельзя ждать. Вот цитата из DDK: Callers of KeWaitForSingleObject must be running at IRQL <= DISPATCH_LEVEL. Usually, the caller must be running at IRQL = PASSIVE_LEVEL and in a nonarbitrary thread context. A call while running at IRQL = DISPATCH_LEVEL is valid if and only if the caller specifies a Timeout of zero. That is, a driver must not wait for a nonzero interval at IRQL = DISPATCH_LEVEL.
" is valid if and only if the caller specifies a Timeout of zero." У меня тоже стоит 0. К тому же при первом вызове она ждет как положенно.
"А чего тогда ждем?" Event. Стоит в первоим парамметре KeWaitForSingleObject'а "нужно увидеть код" Написанный на C++ пойдет?
"Я не понимаю, зачем его ждать при нулевом таймауте." В книге Солдатова "Прогарммирование драйверов" говорится, что значении Timeout = NULL - это " при безусловном (неограниченном)ожидании". Правда здесь под воросом, что,интересно, значит "безусловном". В главном потоке: case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER: { PUCHAR BufferString; struct _URB_BULK_OR_INTERRUPT_TRANSFER *pBulkOrInterruptTransfer = (struct _URB_BULK_OR_INTERRUPT_TRANSFER *) pUrb; //На эту ф-ию можно не обращать вниммания. BufferTransfer(devext, (PUCHAR) pBulkOrInterruptTransfer->TransferBuffer, pBulkOrInterruptTransfer->TransferBufferMDL, (ULONG)pBulkOrInterruptTransfer->TransferBufferLength); //Запускаю дочерний поток KeSetEvent(devext->Event2,IO_NO_INCREMENT,FALSE); //Жду пока выполнится цикл в другом потоке. KeWaitForSingleObject(devext->Event1,Executive,KernelMode,FALSE,(PLARG E_INTEGER)NULL); } break; В дочернем: while(1) { KeWaitForSingleObject(((PDEVICE_EXTENSION)arg)->Event2,Executive,Kerne lMode,FALSE,0); if(((PDEVICE_EXTENSION)arg)->BUFFER ==-1) { KeSetEvent((((PDEVICE_EXTENSION)arg)->Event1),IO_NO_INCREMENT,FALSE) ; PsTerminateSystemThread(0); } else WriteLog(((PDEVICE_EXTENSION)arg)->BUFFER,-1); //Запускаю главный поток KeSetEvent((((PDEVICE_EXTENSION)arg)->Event1),IO_NO_INCREMENT,FALSE) ; } Тип эвонтов - Synchronization. Смысл в том, что нужно чтобы они работали поочередно т.е запускали\останавливали друг друга.
Это значит, что ожидание может завершиться только когда наступит ожидаемое событие. Но Timeout = NULL и нулевой таймаут это совсем разные вещи, первый означает бесконечное ожидание, а второй - нулевой интервал таймаута. И если делаешь KeSetEvent, то что у тебя сбрасывает евент? Тогда нужно после ожидания делать KeClearEvent или KeSetEvent заменить на KePulseEvent (не рекомендую).
<font color="gray][ JNTT</font><!--color--><font color="gray]: В книге Солдатова "Прогарммирование драйверов" говорится, что значении Timeout = NULL - это при безусловном (неограниченном)ожидании". Правда здесь под воросом, что,интересно, значит "безусловном". ]</font><!--color--> Добавлю... Есть три варианта использования параметра Timeout: 1. NULL - бесконечное ожидание. 2. Timeout.QuadPart = -X - ждем X интервалов по 100нс или можно определить абсолютное время. 3. Timeout.QuadPart = 0 - это и есть нулевой таймаут. Никакого ожидания при этом не происходит. Используется для проверки состояния ожидаемого объекта. Это единственный случай, когда IRQL м.б. = DISPATCH_LEVEL. Под "условным" ожиданием Солдатов, видимо, понимает ожидание в тревожном состоянии. Параметр Alertable = TRUE.
И если делаешь KeSetEvent, то что у тебя сбрасывает евент? При типе эвонтов "Synchronization" эту работу проделывет KeWaitxxx. "1. NULL - бесконечное ожидание. 3. Timeout.QuadPart = 0" А я совсем и забыл, что парамметр типа PLARGE_INTEGER... ) "можно определить абсолютное время." Что это такое абсолютное время?
Извини, не обратил внимания. Это значит время, которое функция будет ожидать события. Если таймаут истек, то возвращается STATUS_TIMEOUT. Все равно на dispatch это тебе ничем не поможет.
"Все равно на dispatch это тебе ничем не поможет." Пожалуй, докой DDK и парой BSOD'ов я в этом хорошо убедился.) Если на уровне dispatch нельзя перейти в ожидание, то как же тогда быть? Гонять KeWaitxxx в цикле и проверять возвращаемое значение? Помоему тупо.(
Если тебе по установке эвента нужно выполнять какие-либо действия, то цепляйся к рабочему потоку (IoAllocateWorkItem/IoQueueWorkItem) и там можешь ждать сколько угодно. Можно поставить APC какому-нибудь другому потоку. Но если тебе обязательно нужно задержать поток на dispatch, то имхо придется обломиться.
интересно зачем они вообще сделали работу Wait ф-ий при IRQL = DISPATCH_LEVEL, толку от них все равно мало.