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

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Очередь IRP пакетов  (Прочитано 21429 раз)
0 Пользователей и 7 Гостей смотрят эту тему.
acc15
Гость
« : 01-02-2006 16:19 » new

сделал полностью свою очередь, т.е. не Cancel-safe не Interlocked, а полностью свою.
Вроде как работает, но пару вопросов касающихся проверки этого чуда:

1. Как мне посылать IRP пакеты на драйвер одновременно, т.е. чтобы они попали в 1 и тот же момент,
пробовал два потока, и оттуда DeviceIoControl (соотв. всё синхронно,всмысле одновременно), в итоге они приходят последовательно... хотя DDK говорит что есть вероятность одновременного прихода IRP пакетов, даже в однопроцессорных системах... вот как мне сделать эту вероятность побольше? или DDK обманывает?

2. Может очередь я зря делал?
« Последнее редактирование: 01-02-2006 16:21 от acc15 » Записан
Ochkarik
Модератор

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

« Ответ #1 : 02-02-2006 08:24 » 

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

что можно придумать для отладки.... необходимо обеспечить некоторую продолжительность выполнения запросов. для этого можно в тело обработки запроса вставить например слип на несколько секунд))) - если на уровне пассив все происходит. Операционка в этом случае начнет переклчюать контекст а вдругих контекстах могут быть свои запросы.
далее запустить кучку потоков (приложений) которые одновременно пытаются вызвать ваш драйвер. короче барабанят по нему длинной очередлю запросов.
Кстати вопрос... вообще говоря нумеговская генерилка сишного (без плюсов) кода формирует обработку этой самой очереди и помоему достаточно неплохо. я сильно в ней не разбирался, пока смысла в очередях у меня не случалось.
 в связи с чем вопрос - очередь на IRP какого типа? IOControl? MN_PNP, MN_Power? по ряду PNP запросов необходимо приостанавливать очереди и перезапускать заново... вы это учитывали?

еще момент... если у вас гипер-тренинг-проц, то так все и происходит.

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

кстати вы очередь на чем строили? и чем синхронизировали?
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
acc15
Гость
« Ответ #2 : 02-02-2006 15:35 » 

Вообще очередь должна проходить через все ф-ции вызываемые менеджером.
Принцип таков, может туповат, но работает:
Все MajorFunctions(используемые) инициализ. на некую ф-цию приёма пакетов, которая собственно засовывает эти пакеты в очередь.

Есть дополнительный поток(уровня ядра) который обрабатывает эти запросы(Естественно код обработки исполняется уже не в контексте пользователя).
т.е. схема такова

Пакет -> SpinLock -> В очередь-> ReleaseSpinlock -> Пробуждение потока(если неактивен)(собственно KeSetEvent события которого ждёт поток) -> Если поток занят обработкой значит только что пришедший пакет продолжает сидеть в очереди, если нет начинается обработка только что пришедшего пакета(в контексте ядра) -> Обработка -> Удаление пакета и так снова и снова, пока не кончится очередь -> Ожидание события (того которого устанавливает ф-ция приёма IRP пакетов).

IRP_MJ_PNP... хмм... приостанавливать? всмысле тот поток? а перезапускать это пробуждать поток?

Очередь именно и нужна, есть такие операции, где к примеру требуется отсылать/принимать некоторый объём данных через плату, так вот когда плата завершила обмен она генерирует прерывание, его то мне и надо ждать, поэтому очередь необходима.... да ещё и ddk припугнул
Цитата
Because the I/O Manager supports asynchronous I/O within a multitasking and multithreaded system, I/O requests to a device can come in faster than its driver can process them to completion, particularly in multiprocessor machines.

Синхронизация: ф-ции удаления, добавления пакетов используют только IntelockedXxx
« Последнее редактирование: 02-02-2006 16:02 от acc15 » Записан
Ochkarik
Модератор

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

« Ответ #3 : 02-02-2006 15:56 » 

под приостановкой очереди и перезапуском ее я имел в виду что по некоторым PNP запросам типа IRP_MN_QUERY_XXX необходимо приостановить выполнение очереди, в случае IRP_MN_CANCEL_XXX возобновить выполнение.
в случае продолжения например IRP_MN_QUERY_STOP_DEVICE->IRP_MN_STOP_DEVICE завершать их обработку.
и с запросами по MN_Power тоже что то хитрое...
это я в общих чертах говорю, конечно, поскольку сам так и не удосужился разобраться... мы в нашей работе от прерываний отказались - у нас по большей части только высокоскоростной ввод дечерз мастер-дма используется...

первым делом как найду время разбираться - начну нумеговкие рыбы изучать более подробно... собственно тоже посоветовал бы, там аккуратно должно быть сделано. правда кто то тут на реализацию этих рыб для плюсов ругался... то ли по USB то ли по 1394. там какой то баг в классах был.. но я все равно придерживаюсь использования чистых С-ей, для написания тела драйвера при использовании например той же нумеговской "генерилки" новых проэктов...
по крайней мере той части что за диспечиризацию отвечает.

PS спинлок это хорошо... помоему он interlocked использует тоже ... кстати там в компиляторе есть опция под мультипроцессорность?
у меня была задача под синзронизацию потоков передачи данных из драйвера в приложения... сделал на interlocked функциях... жалко было лишний Call ядра делать, и неудобно было префикс lock в ассемблере самому вставлять... остановился на InterlockedAdd и иже с ними) знать бы как грамотно _asm lock add dword ptr, eax вставить...)))
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
acc15
Гость
« Ответ #4 : 02-02-2006 16:13 » 

по поводу Interlocked... там в ntddk.h есть исходы inline ф-ций... они inline, по этому жалеть нет смысла.  да баг в DS генерации есть... ошибка синтаксическая... если использовать cpp, исправлял, компилилось нормально, но проверять нет желания... да и вообще использовать классы в дровах нечто лишнее, драйвер это не такая сложная(по логике) вещь... там лишь нужно грамотно обеспечить доступ к устройству...
« Последнее редактирование: 02-02-2006 16:31 от acc15 » Записан
Ochkarik
Модератор

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

« Ответ #5 : 26-02-2006 14:59 » 

я про interlocked в ring-3 говорил - там call компилится. но я то знаю - ЧТО я хочу получить;)
а если самому _asm написать, то подурацки регистры использоваться начинают...

как красиво компилятор memcpy разворачивает... ХОЧУ ТАК!
а когда еще размер в DWORD переводишь типа memcpy(...,lengthDW<<2) - вааще сказка RTFM
чиста голый вызов rep movsd! Не может быть...

PS про классы - согласен! единомышленник можна сказать!!!!
« Последнее редактирование: 26-02-2006 15:03 от Ochkarik » Записан

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

ru
Offline Offline

« Ответ #6 : 27-02-2006 14:19 » 

"т.е. чтобы они попали в 1 и тот же момент" - как ты это себе представляешь на UP системе, там один поток выполнения, все равно кто то всегда будет первее.
Записан
Ochkarik
Модератор

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

« Ответ #7 : 28-02-2006 11:05 » 

одновременно может и не получится... а вот если вызов на PASSIVE_LEVEL или APC? то переключение задач вполне может произойти.
таким образом один обработка первого запроса прервется, и начнется обработка второго. тем же кодом. об том и была речь, насколько я понял. чем больше обработка - тем больше вероятность переключения потоков.
Записан

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

ru
Offline Offline

« Ответ #8 : 28-02-2006 11:44 » 

"чем больше обработка - тем больше вероятность переключения потоков" - это зависит от приоритетов потоков.
 А вобще то синхронизацию никто не отменял. Драйвера файловых систем постоянно вызываются в параллельных потоках.
Записан
Ochkarik
Модератор

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

« Ответ #9 : 28-02-2006 12:07 » 

1 в принципе да. но если копии одного и того же приложения запускать - у них, что разный приоритет вдруг станет?)
2 ну да, так это и требовалось эмулировать.
3 синхронизацию не отменял, но ее можно и упростить значительно, а можно и по полной... от задачи зависит.
Записан

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

ru
Offline Offline

« Ответ #10 : 28-02-2006 12:44 » 

1. Может не поверишь, но приоритет потока меняется в рамках его группы.
Записан
Ochkarik
Модератор

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

« Ответ #11 : 28-02-2006 14:05 » 

в случае запуска двух компий одной программы, базовые приоритеты процессов и текущие для их потоков - будут идентичны если не извращатся...
и вообще не о том речь....
а так - действительно, других запросов ввода/вывода/ожидания событий и пр... в тестовом потоке приложения лучше не делать. ну и IoCompleteRequest(Irp, IO_NO_INCREMENT) ставить.

PS про планирование потоков я тоже читал  Что, съел?

хм... а вообще пофиг на приоритеты - они то тут причем? вопрос как протестировать корректность написанной диспечиризации?
« Последнее редактирование: 28-02-2006 14:14 от Ochkarik » Записан

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

ru
Offline Offline

« Ответ #12 : 28-02-2006 16:31 » 

 Ну как протестировать, запустить и тестировать. Для увеличения вероятности одновременного входа использовать MP машину.
 А вобще вопрос проверки корректности программы- это не в драйвера вопрос, это целое научное направление- проверка моделей( отсутсвие переходов в запрещенные состояния на графе выполнения программы ), а потом еще и проверка соотвествия кода этой самой модели.
Записан
phirsoff
Гость
« Ответ #13 : 03-03-2006 11:22 » 

To SlavaI.
Вчера на форуме electronix.ru читаю:
Вопрос:
1. Существует ли какое-нибудь открытое (бесплатное) ПО для моделирования, верификации?
2. Никто не подскажет стоящие электр. курсы, книги по данной тематике?

Ну, прям как в газете, "народ интересуется".
А если серьезно, вопрос хороший. Может быть кто ответит?
Записан
acc15
Гость
« Ответ #14 : 03-03-2006 13:37 » 

ПРО "Одновременно". Я думаю такое частенько происходит в многопроц. системах, т.е. частота посылки запрсов может так велика что обработка не успевает завершится... Есть конечно такой кривоватый метод... который называется WaitForSingleObject и сидеть тупо выжидать прерывание, НО при этом приложение запрсившее действие требующее ожидания прерывания подвиснет.
И ещё очень веская причина:
Устройство НЕ поддерживает параллельной работы, т.е. если к примеру вот записали данные в память... обмен начался... и тут влазит 2ая программа тоже с просьбой записать в память... ну я думаю дальше понятно что будет...
Записан
Ochkarik
Модератор

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

« Ответ #15 : 03-03-2006 15:27 » 

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

кстати... а отчего ты interlocked не использовал? это ж единственный механизм синхронизации мультипроцессорных систем. основан на префиксе
lock (асемблерном).
семафоры и мьютексы для синхронизации в мультипроцессорных системах НЕ подойдут. повышение IRQL - тоже НЕТ, имей в виду.
« Последнее редактирование: 03-03-2006 15:35 от Ochkarik » Записан

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

ru
Offline Offline

« Ответ #16 : 03-03-2006 16:18 » 

to Ochkarik - "семафоры и мьютексы для синхронизации в мультипроцессорных системах НЕ подойдут" не несите пожалуйста чепухи! Если вы видели синхронизацию с помощью запрета планировщика на UP системе, это не значит что она так же сделана на MP системе.
 Дарю вам супер способ синхронизации без долгой блокировки вызывающего потока если ему неинтересно ждать результата конечно, называется он очереди- в dispatcher routine вставляете в очередь ExInterlockedInsertTailList, ставите event своему потоку и выходите со статусом STATUS_PENDINGn пометив IoMarkIrpPending(), потом в своем ОДНОМ потоке, который проснется по event, вынимаете и выполняете последовательно ВСЕ что есть в очереди, потом опять на event ждете. Только учитывайте фактор юзермодовских буферов.
 Или самое простое- просто разрешить с помощью любой синхронизации только одному потоку входить- остальным ждать, если IRQL<=APC_LEVEL, если IRQL выше- то очередь, как описано выше.
« Последнее редактирование: 03-03-2006 16:28 от SlavaI » Записан
Ochkarik
Модератор

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

« Ответ #17 : 03-03-2006 17:11 » 

межпроцессорная блокировка может быть релаизовано ТОЛЬКО при использовании префикса lock в асемблере. это единственное что я точно знаю.
PLIST_ENTRY
  ExInterlockedInsertTailList(
    IN PLIST_ENTRY  ListHead,
    IN PLIST_ENTRY  ListEntry,
    IN PKSPIN_LOCK  Lock
    );
PKSPIN_LOCK  - указатель на DWORD который подобной командой ставится/снимается ассемблерной командой с префиксом lock.

синхронизацию при помощи DPC_LEVEL на MP делать нельзя.

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

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
acc15
Гость
« Ответ #18 : 03-03-2006 21:19 » 

Цитата
Дарю вам супер способ синхронизации без долгой блокировки вызывающего потока если ему неинтересно ждать результата конечно, называется он очереди- в dispatcher routine вставляете в очередь ExInterlockedInsertTailList, ставите event своему потоку и выходите со статусом STATUS_PENDINGn пометив IoMarkIrpPending(), потом в своем ОДНОМ потоке, который проснется по event, вынимаете и выполняете последовательно ВСЕ что есть в очереди, потом опять на event ждете. Только учитывайте фактор юзермодовских буферов.

Всё именно так у меня и есть... только вместо ExInterlockedInsertTailList, используется своя ф-ция помещения в очередь, которая использует InterlockedIncrement,Decrement,Exchange(Pointer) и т.д. и т.п. Вроде я об этом писал... а все эти interlockedы --- это ни что иное как INLINE ф-ция!!! т.е. в итоге выходит тот же lock ассемблерный. вот к примеру:

Код:
FORCEINLINE
LONG
FASTCALL
InterlockedCompareExchange(
    IN OUT LONG volatile *Destination,
    IN LONG Exchange,
    IN LONG Comperand
    )
{
    __asm {
        mov     eax, Comperand
        mov     ecx, Destination
        mov     edx, Exchange
   lock cmpxchg [ecx], edx
    }
}
Цитата
PKSPIN_LOCK  - указатель на DWORD который подобной командой ставится/снимается ассемблерной командой с префиксом lock.

В принципе - да...

Цитата
как только смогу запустить софтайс на моей видюхе - узнаю точно.
Интересно и как же ты будешь проверять многопоточность в дебагере? брикпоинты? интересно как... это всё надо без софтайса проверять в живую... в глубоком задумье и ожидании голубенького экрана вслучае неудачи... Эвенты + lock... именно от этих элементов пошли остальные объекты синхронизации... => на этих объектах(ф-циях) можно построить какую угодно синхронизацию...

Кстати вопросик... что физически происходит в МП системах при этом самом lock'е... Остальные процы приостанавливаются или как?
« Последнее редактирование: 20-12-2007 16:18 от Алексей1153++ » Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #19 : 04-03-2006 18:15 » 

to Ochkarik "межпроцессорная блокировка может быть релаизовано ТОЛЬКО при использовании префикса lock в асемблере. это единственное что я точно знаю" , значит вы еще мало знаете если это у вас исключило мьютексы и семафоры.  По вашему при реализации семафоров и мьютексов не используется атомарная операция set and check?
 "синхронизацию при помощи DPC_LEVEL на MP делать нельзя." это и есть отключение планировщика.
 Ваша проблема в том что вы делаете выоды, основываясь на изучение ядра для UP машин, ядро для MP машин всегда использует atomic set and check совместно с отключением планировщика. Замените у себя ядро на ядро для MP машин, для этого есть специальная команда загрузчика.
  И небольшое дополнение - при ограниченном(!) числе потоков их всегда можно синхронизовать без использования атомарной операции.
« Последнее редактирование: 04-03-2006 18:26 от SlavaI » Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines