Среда: Драйвер под ОС Windows. Алгоритм: Программа уровня пользователя формирует запрос DeviceIoControl. По запросу DeviceIoControl драйвер переводит событие в состояние "снято" и запускает на выполнение длительную операцию. Аппаратура по завершении операции формирует прерывание. Обработчик прерываний снимает прерывание и устанавливает событие в "установлено". Программа уровня пользователя делает WaitForSingleObject. Проблема: Таким образом, после запроса длительной опреации WaitForSingleObject гарантированно должно завиксировать установку события, однако с некоторой вероятностью, этого не происходит! Где-то в 1 случае из 10 тыс. WaitForSingleObject выходит по таймауту. Таймаут стремиться к бесконечности (при INFINITY виснет напроч). Самое интересное, если сразу после выхода из функции WaitForSingleObject по таймауту опросить событие, то оно в состоянии "установлено" и на уровне ядра с помощью DbgView видно что событие было установлено и после выхода по таймауту оставалось установлено!!! Можно конечно переделать алгоритм, IRP запрос на обслуживание отложить, а по прерыванию его завершить, но менять структуру уже не хочется. Можно также дважды делать WaitForSingleObject, однако это как то не прилично. Может кто что подскажет.
Без кода трудно будет сказать что-то, может быть при какихто обстоятельствах теряется вызов к KeSetEvent или что-то еще..
Кода слишком много, чтобы его приводить, к сожалению... Теория про то, что теряется вызов я проработал. KeSetEvent всегда выполняется после обработки прерывния и установлен: слово ((ULONG*)(pEvent))[1] == 1. Может если кто знает, при правильно реализованном алгоритме такая ситуация как у меня под ОС WindowsXP вообще возможна? Или это всё же моя ошибка? Не хочется искать чёрную кошку в тёмной комнате когда её там нет. Интересно то, что ошибка увеличивает вероятнсть своего проявления при увеличении интенсивности обмена.
Ура форум в доступе! Нашёл ошибку сам. Проблема была в алгоритме. Нельзя выставить событие в обработчике прерываний, так как согласно DDK KeSetEvent вызывается на уровне IRQL<=DISPATCH_LEVEL. Исправил проблему следующим образом: В обработчике прерывания ставлю в очередь запуск DPC функции. DPC функция выполняется после завершения обработки прерывания на уровне DISPATCH_LEVEL и выставляет событие. Самое забавное, что с такой ошибкой драйвер вообще довольно упешно работал, ошибка проявлялась довольно редко!
Вот так вот не читать допустимые IRQL в ддк ) Вообще, когда ты писал, я думал что ты делаешь какойнить dpc или workitem... а оказалось ты напрямую ставил
Да,кстати, специально, чтобы ловить такие и многие другие ошибки, есть Check Build сборка ядра. Например код KeSetEvent начинается с: ASSERT_EVENT(Event); ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); Чекбилд ядра бы сразу отловил это дело и выдал ассерт. + Driver Verifier тоже много чего ловит. + Static Driver Verifier (или как он там называется в WDK, который анализирует исходный код) Полезные штуки, а мало кто использует, к сожалению.
Всё хорошо, но есть проблемка. Driver verifier из tools DDK так негативно воспринял мой драйвер, что после настройки и перезагрузки возникала критическая ошибка и винда больше не загружалась. WDK посмотрю. А вот Check Build винды я как то и не надеялся найти дистрибутив. Если не трудно дайте ссылочку. Заранее благодарен за помощь на моём ПУТИ.
Набрать в гугле "Windows XP SP2 Checked Build" религия не позволяет? Первая ссылка на скачку с сайта MS.
Позволила, набрал, скачал. Действительно первая. Предчувствую, что ещё долгое время проведу занимаясь отладкой. Всем спасибо.
весь дистриб не ставь, возьми оттуда тока ntoskrnl и hal и пропиши как ядро и хал в boot.ini соотв. ключами
http://www.osronline.com/ в правой колонке "THE LATEST" всегда есть ссылка на Checked Build Downloads, где перечислены все публично доступные дебужные билды.