Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Связь между драйвером и приложением  (Прочитано 24030 раз)
0 Пользователей и 1 Гость смотрят эту тему.
sinsin
Постоялец

ru
Offline Offline
Пол: Мужской

« : 22-02-2010 12:57 » 

Доброго времени суток.
Переделываю пример passthru из DDK (пользуюсь http://www.wd-3.com/archive/ExtendingPassthru2.htm). Требуется оповещать приложение о каждом принятом с запрещенного ip пакете. На мой взгляд использовать для этой цели событие, оповещающее приложение, и IOCTL будет медленно, поэтому хочу использовать для этого pipe или файлы, проецируемые в память, но возникает такая проблема - обработка пакета идет на  IRQL DISPATCH_LEVEL (например в функции PtReceivePacket), а zwCreateFile, IoCreateFile и т.д. требуют PASSIVE_LEVEL.
Нет ли функций, для  работы с файлами, проецируемыми в память и pipe для DISPATCH_LEVEL?
Как лучше организовать такое оповещение?
Записан
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 22-02-2010 13:30 » 

Я бы не стал в ядре разгуливаться. Информация о ИП это совсем не много (по размеру). Я бы буферизовал блоки такой информации и дальше то самое Событие + IOCTL. Не вижу никаких проблем.
По поводу ZwCreateFile (и иже с ним). Да работает только на PASSIVE_LEVEL. А как ты хотел. Ты в ядре парень, тут шутить не любят   Не-а...
« Последнее редактирование: 22-02-2010 13:38 от resource » Записан
sinsin
Постоялец

ru
Offline Offline
Пол: Мужской

« Ответ #2 : 23-02-2010 06:18 » 

А примера кода такого обмена нигде нет?
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 23-02-2010 09:02 » 

resource, +1 Ага
а насчет использования файлов.. можно в принципе подумать. для простоты реализации со стороны приложения. но это точно не будет быстрее.
я тут все никак руки не доходят разобраться, что надо сделать чтобы под Vista/Seven DeviceIOCintrol без полных админских привилегий проходили)

sinsin,
и кстати с чего вы решили что pipe - это быстро?
и каким образом использование отображаемого файла решает все вопросы синхронизации?) там даже для асинхронного чтения тот же KeSetEvent используется)
насчет примера... я тут кусками выкладывал кое что... поищите по KeSetEvent  и ObReferenceObject. и еще вам потребуется что то типа MmMapLockedPages. - это тоже все было на форуме.
и DDK) потому, что я, к сожалению,  не знаю  аналоги этому среди NDIS функций.
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #4 : 23-02-2010 10:08 » 

Цитата: Ochkarik
что надо сделать чтобы под Vista/Seven DeviceIOCintrol без полных админских привилегий проходили

Я вот знаете ли, как старый дедушка, на XP сижу пока Еще давным давно.... Не в том смысле, что так и надо. Хорошо это или плохо - просто так вот есть.

Цитата: Ochkarik
с чего вы решили что pipe - это быстро?

Я вот сперва и хотел тоже самое написать. По своему опыту работы с пайпами (правда в юзермод), могу сказать, что это довольно небыстрая штука.

Цитата: Ochkarik
не знаю  аналоги этому среди NDIS функций

Ну, если KeSetEvent и ObReferenceObject тоже имелись ввиду, то тут NdisSetEvent есть, а для второй мне кажется ndis аналога нет (правельнее сказать - я такого не знаю). Что касается MmMapLockedPages, которая, кстати говоря, на сегодня считается устаревшей (MmMapLockedPagesSpecifyCache), то я почти уверен что для нее нет ndis обёртки (этож всё макросы которые вызывают оригинальные функции). По крайней мере на странице DKK по NdisAllocateMdl создается именно такое впечатление.

По поводу моего предложения буферизовать блоки данных. Тут главное используй Lookaside list (не люблю переводить этот термин). Не забудь, для них ndis-варианты есть, как например NdisAllocateFromNPagedLookasideList, и всё будет быстро и круто.
Записан
sinsin
Постоялец

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 23-02-2010 13:12 » 

Ochkarik, resource большое спасибо!
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #6 : 23-02-2010 13:46 » 

resource, я тоже на XP... но к будущему готовлюсь)
MmMapLockedPages - это я для поиска по форуму написал) чаще встречается.

Lookaside это хорошо... только вот куда коня то запрягать) в том смысле как данные в приложение отдать? опять через отображаемый файл?
я тоже не нашел аналогов ObReferenceObject и  MmMapLockedPages. видимо подразумевается что NDIS не должен напрямую общатся с приложениями)

есть еще WMI инструментарий... но я им никогда не пользовался. копать надо)
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 23-02-2010 14:48 » 

Цитата: Ochkarik
в том смысле как данные в приложение отдать?

IOCTL или Read/Write если хочется. Если драйвер складирует блоки данных, то на мой взгляд вопрос о молнеиносной передачи этих данных в приложение отпадает сам собой. В этой ситуации суетиться надо уже не драйверу а приложению. В том плане, что событие надо ждать всегда.

Но если поставить вопрос по другому: какой вариант будет наибыстрейшим на отрезке от вызова функции (для получения данных) приложением, до того момента как функция вернет управление, с буффером, полным счастья (считаем что данные у драйвера, уже лежат и ждут когда их заберут)? Думаю, что быстрее мапинга тут врядли что-то будет. Тут и вызывать то ничего не потребуется, когда данные уже в памяти, к которой открыт доступ. Но приложению еще надо узнать начало и конец новых данных в этом буфере. Такие указатели можно записывать в этот же буфер, в несколько первых (или последних) байт. Но тут, как вы понимаете, остро встает проблема их синхронизации. И тут уже получается не самая простая ситуация. Я, честно говоря, даже не знаю как такое синхронизировать: события как-то не в тему, мьютексы на свалку, спинлоков в юзермоде нет, да и дело то не том, что их нет, а в том что драйверу нельзя ждать если нужно писать данные в буфер.

 В реальной ситуации надо конечно серьезно подумать, мапить или не мапить (вот в чем вопрос). Есть свои плюсы и минусы (как банально). Мне кажется для блоков таких малых объемов это лишняя суета. в общем по ситуации. Универсальных решений не существует (наверное).

P.S. Я WMI тоже не пользовался никогда в жизни
« Последнее редактирование: 23-02-2010 14:53 от resource » Записан
sinsin
Постоялец

ru
Offline Offline
Пол: Мужской

« Ответ #8 : 23-02-2010 15:10 » 

Ochkarik, resource, если нет аналога ObReferenceObject, получается, что никак нельзя передать событие? А как тогда  можно сообщить приложению о том, что  имеются данные для чтения?
Записан
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #9 : 23-02-2010 15:14 » 

Если нет аналога ObReferenceObject это не значит, что нельзя использовать саму ObReferenceObject   Ага
Записан
sinsin
Постоялец

ru
Offline Offline
Пол: Мужской

« Ответ #10 : 23-02-2010 15:22 » 

Я  знаю, что можно, но в неё передается  Object, который   the caller obtained this parameter either when it created the object or from a preceding call to ObReferenceObjectByHandle after it opened the object, а ObReferenceObjectByHandle действует только на Passive_Level. Я создаю событие в приложении и пытаюсь передать его в драйвер по Handle. Как можно получить указатель на событие по Handle без ObReferenceObjectByHandle?  И как лучше здесь будет передать событие?
« Последнее редактирование: 23-02-2010 15:29 от sinsin » Записан
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #11 : 23-02-2010 15:31 » 

Во первых: за чем тебе вообще нужна ObReferenceObject? Ведь, как я полагаю, ObReferenceObjectByHandle тоже увеличивает счетчик ссылок.
Во вторых: ну и вызывай себе ObReferenceObjectByHandle на PASSIVE_LEVEL, что тебе мешает?
Записан
sinsin
Постоялец

ru
Offline Offline
Пол: Мужской

« Ответ #12 : 23-02-2010 15:37 » 

Мешает то, что я передаю Handle по ioctl,  и в процедуре обработки пытаюсь получить событие, а эта процедура выполняется  на DISPATCH_LEVEL. Я в драйверах новичок, поэтому вопрос: кроме ioctl через что можно передать данные?
« Последнее редактирование: 23-02-2010 15:47 от sinsin » Записан
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #13 : 23-02-2010 15:45 » 

Многие ирпы, в том числе и IRP_MJ_DEVICE_CONTROL (твой ioctl) приходит на PASSIVE_LEVEL. Там и получай событие. Посмотри в DDK Dispatch Routines and IRQLs. Максимум на чем может прийти IRP_MJ_DEVICE_CONTROL это APC_LEVEL, но тебе это вряд ли грозит. Чтоб спокойнее было, можешь проверять текущий  IRQL
Записан
sinsin
Постоялец

ru
Offline Offline
Пол: Мужской

« Ответ #14 : 23-02-2010 16:53 » 

Спасибо. Понял.
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #15 : 23-02-2010 18:19 » 

resource, в ring-3 spinlock-ов нет) но почему все забывают о interlocked функциях? это ж так сказать "нативная" синхронизация на уровне команд процессора(-ов) Ага
все объекты блокировки и синхронизации ядра в конечном счете на них построены)
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #16 : 23-02-2010 22:53 » 

Ochkarik, согласен.

Кстати какой вариант лучше подойдет в такой ситуации (два 32х-битных числа, лежат рядом), например так?
Код:
Happiness = InterlockedAnd64(Address, 0xFFFFFFFFFFFFFFFF);

Я вот подумал. Всё равно, как-то нехорошо получается. Что если буфер наполнится (драйвером) гораздо быстрее, чем считается (приложением). Теоретически такое возможно, особенно если учесть, что ProtocolReceivePacket может быть вызвана на DISPATCH_LEVEL. Сам буфер-то не сблокирован (это была бы жесть). А тут уже может получиться что угодно. Сделать большой буфер? Можно, но это из серии - надежда на удачу, т.е. теоретически гарантий не дает.

И еще, возвращаясь к изначальному посту автора топика, я не пойму причем тут файлы, проецируемые....блабла. Мапить надо память (память в память) а не файл.
« Последнее редактирование: 23-02-2010 23:31 от resource » Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #17 : 25-02-2010 06:58 » 

насчет InterlockedAnd64 - не знаю, никогда не применял.... надо инструкции проца смотреть, не уверен что на 32битной платформе оно поддержано нативно, хотя все может быть.

а размер буфера обычно выбирается исходя из максимального потока деленного на частоту опроса + запас)
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #18 : 25-02-2010 07:36 » 

 Ну а какую interlocked функцию вы бы порекомендовали в данной ситуации. Напомню: надо прочитать два 32х-битных числа, которые лежат рядом.
 Просто я, было дело, записывал значение "интерлоками", но вот читать не читал, поэтому не знаю, что тут лучше, ведь они все пишут/обменивают. Или InterlockedAnd вполне то, что надо и тут вопрос только в поддержке/неподдержке x64 ?
 Кстати InterlockedAnd64 помоему без проблем должен поддерживаться на x32.

Код:
LONGLONG __cdecl InterlockedAnd64(
  __inout  LONGLONG volatile* Destination,
  __in     LONGLONG Value
);

а LONGLONG это как известно (из того же SDK)
Код:
#if !defined(_M_IX86)
 typedef __int64 LONGLONG;
#else
 typedef double LONGLONG;
#endif

так что хоть и через ж... дабл, но поддерживается. В юзермоде наверное не супер критично дабл или не дабл, а в ядре, сами понимаете  Не-а... .

кстати есть в winbase.h и такое
Код:
#if !defined (InterlockedAnd)

#define InterlockedAnd InterlockedAnd_Inline

FORCEINLINE
LONG
InterlockedAnd_Inline (
    __inout LONG volatile *Target,
    __in    LONG Set
    )
{
    LONG i;
    LONG j;

    j = *Target;
    do {
        i = j;
        j = InterlockedCompareExchange(Target,
                                       i & Set,
                                       i);

    } while (i != j);

    return j;
}

#endif

такая вот замануха. Но там же есть и нормальный прототип.
« Последнее редактирование: 25-02-2010 07:45 от resource » Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #19 : 26-02-2010 20:42 » 

я не совсем об этом. строго говоря что есть "полноценная" interlocked функция? - это ОДНА машинная команда, выполнение которой, самим процессором выполняется "атомарно" независимо от уровня привелегий, IQRL и аппаратных/программных прерываний.
такие операции могут быть реализованы аппаратно на основе следующих машинных команд x86 архитектуры (к примеру)
InterlockedCompareExchange
CMPXCHG - команда может быть 8/16/32 битной.
или CMPXCHG8B  - делает  "Compare EDX:EAX with m64. If equal, set ZF and load ECX:EBX into m64. Else, clear ZF and load m64 into EDX:EAX."

причем обе команды выполняются с обязательным префиксом LOCK!!!! данных префикс обязывает процессор выдать сигнал LOCK грубо говоря на одну из ножек процессора, чтобы заблокировать выполнение операций модификации памяти на других процессорах, модификаций кэша(или еще где либо). .... очень грубо говоря (точнее не разбирался))!

причем приведенные выше инструкции:
"This instruction is not supported on Intel processors earlier than the Intel486 processors." и "This instruction is not supported on Intel processors earlier than the Pentium processors" соответственно!

реализация моей любимой InterlockedExchangeAdd, основана на команде XADD с префиксом LOCK.
для нее, как мы видим, существует только 32 битная реализация. но зато она есть и в ring-0 и в ring-3, чем очень удобно пользоваться.

а вот очень похожая команда ядра ExInterlockedAddLargeInteger (для 64 битных аргументов) в kernel уже реализована через дополнительный SpinLock (что в пользовательском режиме - просто невозможно... ну или довольно проблематично) и оно понятно - нет соответствующей команды процессора!

 Упомянутая вами InterlockedAnd64 существует только для архитектур IPF и x64 по той же причине. и аналога в kernel - для нее нет...
что до ее реализации в Winbase.h...  честно говоря наверно ребятам виднее. возможно они играют на тонкостях оптимизации и особенностях переключения нитей. честно скажу - не знаю) поэтому не использую, во избежание) да и надобности не было.

вот такая катавасия)
кстати я тут может быть, немного ошибок в описании наделал. но в качестве иллюстрации - все выглядит как-то так)
PPS строго говоря я с этим довольно давно разбирался... но кажется реализация именно такая) если у кого стоит отладчик ядра - поставьте бряки на указанные функции (в SoftIce это было можно, посмотрите глазами?)


PPS еще один момент. для interlocked функций ядра надо внимательно смотреть на строчку типа
"Interlocked operations cannot be used on non-cached memory." (для InterlockedAnd) - что означает то, что в случае свопируемой памяти, будет сгенерировано исключение с последующей подгрузкой недостающих страниц в оперативную память. что нарушит атомарность выполнения функции.

или "InterlockedCompareExchange is designed for speed and, typically, is implemented inline by a compiler. InterlockedCompareExchange is atomic only with respect to other InterlockedXxx calls. It does not use a spin lock and can be safely used on pageable data." - - что означает что оба процесса должны использовать доступ к переменной с использованием префикса lock.

таким образом я для себя выделил два основных момента:
атомарная interlocked функция над одной переменной может быть использована(для синхронизации доступа из приложения и драйвера) только в случае:
1. не свопируемой переменной.
2. только в случае если реализация функции может быть выполнена машинной командой с префиксом LOCK. (без используется дополнительного spinLock-а).
я примерно так и поступаю)
« Последнее редактирование: 28-02-2010 18:26 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
PredatorAlpha
Помогающий

us
Offline Offline

« Ответ #20 : 28-02-2010 10:14 » 

Но приложению еще надо узнать начало и конец новых данных в этом буфере. Такие указатели можно записывать в этот же буфер, в несколько первых (или последних) байт. Но тут, как вы понимаете, остро встает проблема их синхронизации. И тут уже получается не самая простая ситуация.

А что за проблема? Драйвер пишет указатель записи после того, как данные записаны, а приложение модифицирует указатель чтения только после того, как вычитаны данные. Проблема синхронизации может быть только, если запись или чтение может осуществляться с нескольких асинхронных потоков одновременно.
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #21 : 28-02-2010 19:32 » 

PredatorAlpha, да проблем никогда нет) есть только поиски оптимальных решений)
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #22 : 01-03-2010 15:46 » 

в догонку моему посту про interlocked-функции.
раньше делал их вручную))) пока в DDK не нашел))
Не может быть...
Код:
void __inline
InterlockedAdd( unsigned long ptr_value,  unsigned long  value)
{
    _asm {                                     
        mov edi, dword ptr[ptr_value];
        mov edx, value;   
        lock add dword ptr[edi],edx;   
    };
    return;
};

или еще вот так делал:
Код:
    
_asm
    {
        mov edx, lpSpinLockBlockCount;
        lock mov dword ptr[edx], 123;
    };
//какой то код для защиты
    _asm
    {
        mov edx, lpSpinLockBlockCount;
        lock mov dword ptr[edx], 0;
    };
Жжешь
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
alkor
Новенький

ru
Offline Offline

« Ответ #23 : 05-06-2010 06:37 » 

Я бы не стал в ядре разгуливаться. Информация о ИП это совсем не много (по размеру). Я бы буферизовал блоки такой информации и дальше то самое Событие + IOCTL. Не вижу никаких проблем.

можно поподробнее  Улыбаюсь
Записан
resource
Молодой специалист

ru
Offline Offline
Пол: Мужской

« Ответ #24 : 05-06-2010 09:46 » new

Цитата: alkor
можно поподробнее  Улыбаюсь

А насколько подробнее?  Улыбаюсь

Всё, что вам надо:
1. Знать, что такое двусвязный список и как им пользоваться
http://msdn.microsoft.com/en-us/library/ff563802(VS.85).aspx
2. Уметь выделять память
http://www.wasm.ru/series.php?sid=9 - 6я и 7я части
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines