Отложенная обработка irp
От: block_head  
Дата: 29.01.07 11:53
Оценка:
Разрабатывается TDI — фильтр, который при любой сетевой активности должен спросить у юзер-мод приложения — разрешить или нет. Вопрос следующий — как правильно организовать ожидание ответа от приложения в драйвере. Как я понимаю есть два способа — объявить irp как pending или поместить в очередь. В этом деле я новичок, так что возможно что — то пропустил. В форуме есть некоторые наметки к ответу но нигде нет конкретного ответа (либо чего не понял).
Re: Отложенная обработка irp
От: TarasCo  
Дата: 29.01.07 14:58
Оценка:
Здравствуйте, block_head, Вы писали:

_>Разрабатывается TDI — фильтр, который при любой сетевой активности должен спросить у юзер-мод приложения — разрешить или нет. Вопрос следующий — как правильно организовать ожидание ответа от приложения в драйвере. Как я понимаю есть два способа — объявить irp как pending или поместить в очередь.


Это в принципе, одно и тоже. Просто речь идет о том, что Вы можете поддерживать очередь отложенных IRP в своем драйвере или оставить это на откуп системе. Вам придется поддерживать собственную очередь ( это не обязательно будет именно очередь — это может быть список, массив, хоть хеш таблица ). Дело в том, что Вам необходимо обрабатывать IRP в ответ на реакцию пользователя — т.е самостоятельно извлекать нужный пакет IRP из какого то хранилища, причем скорее всего это не будет FIFO очередь. Разработчики драйверов устройств часто сталкиваются с ситуацией, когда устройство элементарно занято и нужно накапливать запросы в FIFO очереди. Для этого частого случая ОС имеет поддержку таких очередей. Чтобы воспользоваться этим сервисом, драйвер имеет специальную точку входа, заданную в DRIVER_OBJECT — StartIo, а система предоставляет функции IoStartPacket и IoStartNextPacket для управления этой очередью. В любом случае, диспетчерский обработчик, отложивший обработку IRP должен вернуть STATUS_PENDING и отметить IRP как отложенное ( IoMarkIrpPending ).

Если говорить про TDI — не всякий запрос может быть безопасно отложен. Например драйвер netbt.sys может неправильно вести при получении статуса STATUS_PENDING на некоторые типы запросов, которые он предполагал будут выполнены синхронно.
Да пребудет с тобою сила
Re[2]: Отложенная обработка irp
От: Sergey Storozhevykh Россия  
Дата: 29.01.07 15:13
Оценка:
Здравствуйте, TarasCo, Вы писали:

TC>Это в принципе, одно и тоже. Просто речь идет о том, что Вы можете поддерживать очередь отложенных IRP в своем драйвере или оставить это на откуп системе. Вам придется поддерживать собственную очередь ( это не обязательно будет именно очередь — это может быть список, массив, хоть хеш таблица ). Дело в том, что Вам необходимо обрабатывать IRP в ответ на реакцию пользователя — т.е самостоятельно извлекать нужный пакет IRP из какого то хранилища, причем скорее всего это не будет FIFO очередь. Разработчики драйверов устройств часто сталкиваются с ситуацией, когда устройство элементарно занято и нужно накапливать запросы в FIFO очереди. Для этого частого случая ОС имеет поддержку таких очередей. Чтобы воспользоваться этим сервисом, драйвер имеет специальную точку входа, заданную в DRIVER_OBJECT — StartIo, а система предоставляет функции IoStartPacket и IoStartNextPacket для управления этой очередью. В любом случае, диспетчерский обработчик, отложивший обработку IRP должен вернуть STATUS_PENDING и отметить IRP как отложенное ( IoMarkIrpPending ).


Можно упростить себе жизнь, воспользовавшись механизмом Cancel-Safe IRP Queues
Re: Отложенная обработка irp
От: Sergey Storozhevykh Россия  
Дата: 29.01.07 15:17
Оценка:
Здравствуйте, block_head, Вы писали:

_>Разрабатывается TDI — фильтр, который при любой сетевой активности должен спросить у юзер-мод приложения — разрешить или нет. Вопрос следующий — как правильно организовать ожидание ответа от приложения в драйвере. Как я понимаю есть два способа — объявить irp как pending или поместить в очередь. В этом деле я новичок, так что возможно что — то пропустил. В форуме есть некоторые наметки к ответу но нигде нет конкретного ответа (либо чего не понял).


Calling User Mode — Using the Inverted Call Model
How Drivers Notify User-Mode Apps of Asynchronous Events
LPC communication
Event Sample Driver for Windows 2000
Re[3]: Отложенная обработка irp
От: TarasCo  
Дата: 29.01.07 15:26
Оценка:
Здравствуйте, Sergey Storozhevykh, Вы писали:

SS>Можно упростить себе жизнь, воспользовавшись механизмом Cancel-Safe IRP Queues


Вроде как только начиная с XP? И IMHO, жизнь упроститься не на порядки, можно и ручками cancel routine установить .
Да пребудет с тобою сила
Re[4]: Отложенная обработка irp
От: Sergey Storozhevykh Россия  
Дата: 29.01.07 15:41
Оценка: +2
Здравствуйте, TarasCo, Вы писали:

TC>Здравствуйте, Sergey Storozhevykh, Вы писали:


SS>>Можно упростить себе жизнь, воспользовавшись механизмом Cancel-Safe IRP Queues


TC>Вроде как только начиная с XP?


Не, просто документация местами противоречивая. Вот что соответствует действительности (испытано на себе :) ).

The cancel-safe IRP queue framework is included with Windows XP and later operating systems. Drivers that must also work with Windows 2000 and Windows 98/Me can link to the csq.lib library that is included in the Windows Driver Kit (WDK). The csq.lib library provides an implementation of this framework.


TC>И IMHO, жизнь упроститься не на порядки, можно и ручками cancel routine установить :).


Не на порядки, конечно. Но реализуя cancellation собственными силами, нужно очень много нюансов держать в голове ;)
The Truth About Cancel — IRP Cancel Operations (Part I)
The Truth About Cancel — IRP Cancel Operations (Part II)
Re[5]: Отложенная обработка irp
От: block_head  
Дата: 30.01.07 12:34
Оценка:
Здравствуйте, Sergey Storozhevykh, Вы писали:

убедительная просьба следить за объемом цитирования — модератор

Но обе эти функции: IoStartPacket и IoStartNextPacket сразу пытаются вызвать (если девайс не занят, а в моем случае это так) StartIO которая должна, как я понимаю, быстро обработать запрос.Все же вопрос открытый. Sergey Storozh… — спасибо за ссылки но с event'ами я уже разобрался а вот Calling User Mode — Using the Inverted Call Model пока что довольно сложна в реализации. Можно ли реализовать свою очередь в которой все запросы скапливаются и дальше вниз не пропускаются пока не будет ответа от приложения ?
Re[2]: Отложенная обработка irp
От: block_head  
Дата: 31.01.07 13:08
Оценка:
Здравствуйте, TarasCo, Вы писали:

убедительная просьба следить за объемом цитирования — модератор

С очередями вроде все ясно. Теперь нужно запросы обработать. Ладно если мы запретили, то просто завершаем запрос с access denied. А вот если разрешаем, то необходимо его передать дальше, но для этого необходимо знать куда. У меня есть device_control, который общается с приложением и приаттачиный фильтр. Так вот irp ставится в очередь в фильтре, а вытаскивается (с приходом ответа от приложения) в device_control. Все просто если фильтр один, а если их много, то определить в device_control по irp, к какому фильтру эта irp относится, нельзя. Самое простое решение как я понимаю — отдельно для каждого фильтра создать свою очередь, но есть ли более разумное решение ? Как можно вместе с irp передать информацию о фильтре ?
Re: Отложенная обработка irp
От: block_head  
Дата: 01.02.07 13:48
Оценка:
Здравствуйте, block_head, Вы писали:

_>Разрабатывается TDI — фильтр, который при любой сетевой активности должен спросить у юзер-мод приложения — разрешить или нет. Вопрос следующий — как правильно организовать ожидание ответа от приложения в драйвере. Как я понимаю есть два способа — объявить irp как pending или поместить в очередь. В этом деле я новичок, так что возможно что — то пропустил. В форуме есть некоторые наметки к ответу но нигде нет конкретного ответа (либо чего не понял).


Прошу не игнорировать мои посты )). Как отлаживать irp по пути вниз понятно, а что делать когда необходимо irp притормозить в completion routine. Т.е., например, когда обрабатывается TDI_RECEIVE_DATAGRAM вся информация о соединении будет доступна только по пути наверх, т.е. в completion routine, и в этот момент мне надо отложить irp и спросить разрешение. Как я понимаю, действовать по тому же сценарию, как по пути вниз, нельзя или я ошибаюсь ? Или возвратить в completion routine STATUS_MORE_PROCESSING_REQUIRED, обработать irp и завершить его ?
Re[2]: Отложенная обработка irp
От: TarasCo  
Дата: 02.02.07 07:20
Оценка:
Здравствуйте, block_head, Вы писали:


_>Прошу не игнорировать мои посты )).


Вам ответит первый освободившийся оператор, не вешайте трубку.

_>Как отлаживать irp по пути вниз понятно, а что делать когда необходимо irp притормозить в completion routine. Т.е., например, когда обрабатывается TDI_RECEIVE_DATAGRAM вся информация о соединении будет доступна только по пути наверх, т.е. в completion routine, и в этот момент мне надо отложить irp и спросить разрешение. Как я понимаю, действовать по тому же сценарию, как по пути вниз, нельзя или я ошибаюсь ? Или возвратить в completion routine STATUS_MORE_PROCESSING_REQUIRED, обработать irp и завершить его ?


Если Вы вернете STATUS_MORE_PROCESSING_REQUIRED продолжится завершение запроса — будут вызваны следующие в стеке completion routine, а Вы полностью потеряете над ним контроль. В Вашем конкретном примере это приведет к тому, что датаграмма будет принята. Вы можете в принципе задержать завершение Irp. Для этого нужно вернуть STATUS_SUCCESS. Возобновить прерванное завершение запроса можно вызвав IoCompleteRequest.
Да пребудет с тобою сила
Re[3]: Отложенная обработка irp
От: block_head  
Дата: 02.02.07 07:37
Оценка:
Здравствуйте, TarasCo, Вы писали:

убедительная просьба следить за объемом цитирования — модератор

Как так — возвратить STATUS_SUCCESS, это же тоже приведет к вызове верхних completion routine, может имелось ввиду возвратить STATUS_PENDING ? Или тогда я ничего не понимаю ...
Re[3]: Отложенная обработка irp
От: Sergey Storozhevykh Россия  
Дата: 02.02.07 07:46
Оценка: +1
Здравствуйте, TarasCo, Вы писали:

TC>Если Вы вернете STATUS_MORE_PROCESSING_REQUIRED продолжится завершение запроса — будут вызваны следующие в стеке completion routine, а Вы полностью потеряете над ним контроль. В Вашем конкретном примере это приведет к тому, что датаграмма будет принята. Вы можете в принципе задержать завершение Irp. Для этого нужно вернуть STATUS_SUCCESS. Возобновить прерванное завершение запроса можно вызвав IoCompleteRequest.


Не, наоборот STATUS_SUCCESS, кстати имеет псевдоним STATUS_CONTINUE_COMPLETION
Re[4]: Отложенная обработка irp
От: TarasCo  
Дата: 02.02.07 08:10
Оценка:
Здравствуйте, Sergey Storozhevykh, Вы писали:

SS>Не, наоборот STATUS_SUCCESS, кстати имеет псевдоним STATUS_CONTINUE_COMPLETION


Ну да
Да пребудет с тобою сила
Re[2]: Отложенная обработка irp
От: Sergey Storozhevykh Россия  
Дата: 02.02.07 08:35
Оценка:
Здравствуйте, block_head, Вы писали:

_>Прошу не игнорировать мои посты )). Как отлаживать irp по пути вниз понятно, а что делать когда необходимо irp притормозить в completion routine. Т.е., например, когда обрабатывается TDI_RECEIVE_DATAGRAM вся информация о соединении будет доступна только по пути наверх, т.е. в completion routine, и в этот момент мне надо отложить irp и спросить разрешение. Как я понимаю, действовать по тому же сценарию, как по пути вниз, нельзя или я ошибаюсь ? Или возвратить в completion routine STATUS_MORE_PROCESSING_REQUIRED, обработать irp и завершить его ?


Зачастую CR вызывается на DISPATCH_LEVEL, что представляет проблему, когда необходимо обработать результаты завершения ввода-вывода на более низком IRQL, например, в вашем случае, это "спросить разрешение". Причем, насколько я понимаю, спрашивать вы собрались user-mode?

Примерный вариант реализации completion routine. В случае высокого IRQL, обработка IRP откладывается путем постановки в очередь WorkItem — ScCompletionWorkerRoutine, иначе обрабатываем внутри CR — ScProcessIrpCompletion.

    
    PTRACE_RECORD_LIST recordList = (PTRACE_RECORD_LIST)Context;
    
    //
    //  If we are not at passive level, we should queue this work to a 
    //  worker thread using the workitem that is in Context.
    //

    if (KeGetCurrentIrql() > PASSIVE_LEVEL) {

        //
        //  We are not at passive level, but we need to be to do our work,
        //  so queue off to the worker thread.
        //    
            
        IoQueueWorkItem( recordList->WorkItem,
                         ScCompletionWorkerRoutine,
                         DelayedWorkQueue,
                         Context);

        return STATUS_MORE_PROCESSING_REQUIRED;
            
    } else {
     
        IoFreeWorkItem( recordList->WorkItem );
    }

    //
    //  Do completion processing
    //

    ScProcessIrpCompletion( Irp, recordList );
        
    return STATUS_SUCCESS;


В нашей отложенной процедуре, обрабатываем результаты — ScProcessIrpCompletion, завершаем оригинальный IRP

    //
    //  Do completion log processing
    //

    ScProcessIrpCompletion( irp, recordList );

    //
    // Cleanup before exiting from the worker thread.
    //
    
    IoFreeWorkItem( workItem );
    
    //
    //  Continue completion
    //

    IoCompleteRequest( irp, IO_NO_INCREMENT );



В вашем случае эта схема может видоизмениться с учетом специфики реализации TDI-фильтра — тут я не могу ничего подсказать. И к тому же это самый простой вариант — предполагается что обработка завершится в не слишком длительный период времени, иначе придется озаботиться cancellation и логика может усложниться в разы. См. I/O Completion/Cancellation Guidelines

Reasonable period means here less than 10 seconds for most operations and their cancellations. This time is derived from a user's tolerance to delays when closing an application or canceling an I/O operation that the user perceives is taking too long. It should be much shorter for most operations. There may also be legitimate reasons for it to be longer for some types of devices and/or operations.


Успехов!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.