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

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

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

« : 01-06-2007 07:43 » 

в общем вот такой вопросик...
касается это в первую очередь разработчиков PCMCIA, USB и 1394 подобных интерфейсов которые на ходу могут оторвать.

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

мож ктото уже сталкивался с подобной проблеммой на практике... интересны сами подходы.

PS курю мануалы...
« Последнее редактирование: 01-06-2007 07:47 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
RXL
Технический
Администратор

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

WWW
« Ответ #1 : 01-06-2007 11:03 » 

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

Пользователь лоханулся - выдернул флешку. Ему будет приятно, если его спросят, пофиг ему или он хочет все таки сохранить данные. Соотв., попытаться поймать железку еще раз или поднять наверх ошибку и размонтировать. К примеру, в CD есть блокировка трея, но винда его не лочит, а обрабатывает ошибки.

С точки зрения ПО наверное стоит запросы блокировать до разрешения вопроса.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Ochkarik
Модератор

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

« Ответ #2 : 01-06-2007 15:19 » 

запросы то конечно... иех. просто беда не тогда когда они есть...

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

PS а по этому запросу, в конечном счете, я обязан выгрузить драйвер из памяти. точнее по следующему за ним IRP_MN_REMOVE_DEVICE.

впринципе что еще делать надо - я понимаю, хотя пока не делал - руки не доходили)
но интересно, что еще можно придумать?

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

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

поэтому и вопрос - как можно сделать по другому??? можно вобще все использующие драйвер процессы убить потихому) список их ID у меня драйвер составляет...
« Последнее редактирование: 01-06-2007 15:24 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
RXL
Технический
Администратор

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

WWW
« Ответ #3 : 01-06-2007 19:13 » 

1. Протокол взаимодействия фиксированный или ты можешь его изменить?

2. Что мешает сообщить об ошибке каждому подключенному процессу? Между ними (процессами) есть какая-то связть?
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Ochkarik
Модератор

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

« Ответ #4 : 02-06-2007 09:52 » 

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

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

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

PS процессы обработки независимы. их может быть от одного до нескольких десятков.
« Последнее редактирование: 02-06-2007 09:54 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
RXL
Технический
Администратор

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

WWW
« Ответ #5 : 03-06-2007 10:27 » 

Объясни мне, в чем разница:

1. Данные считаны в память. Всем подключенным процессам посылается событие.
2. Устройство удалено. Всем подключенным процессам посылается событие.

На мой взгляд тут разницы нет. Что же тогда мешает сделать одинаково?
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Ochkarik
Модератор

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

« Ответ #6 : 04-06-2007 12:27 » 

нить обработки данных (пример, не реализация):
Код:
Функция обработки данных вызвается в цикле из нити обработки
  if (буфер данных пустой)
  {
    do{
      WaiteForSingleObject{hEventDrv,...}
    while(пока не появятся новые данные, либо что то еще, таймаут и т.д.)
  }
  обработка данных малая часть (произвольный размер от одного dword и более)...
  уменьшение счетчика необработанных данных: InterlockedDecrement()
  return; 

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

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

---------------------------------------------------------
теперь насчет общей проблеммы.
покопал в выходные литературу, выяснилось что действительно данная проблемма удаления оборудования может быть решена не только придуманным мною способом но и штатным, через функции OC.
(всегда говорю что если вы пользуетесь хорошим продуктом, к которым отношу и винду (и кстати их офис)- там есть ВСЕ, что бы вам не понадобилось:thumbsup:, только это "все" - надо сначала найти)

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

2. так же существуют штатные средства сигнализации удаления устройства (символической ссылки на него, или удаления символической ссылки на его GUID интерфейс).
для этого в приложении регестрируется запрос на получение оконных сообщений WM_DEVICECHANGE об удалении символической ссылки на устройство в драйвере IoDeleteSymbolicLink() (или интерфейса устройства - к сожалению не помню функцию):
RegisterDeviceNotification()/ UnregisterDeviceNotification()
суть:
получаем в драйвере запрос IRP_MN_QUERY_REMOVE_DEVICE (или IRP_MN_SURPRISE_REMOVAL) удаляем символическую ссылку на устройство драйвера: IoDeleteSymbolicLink() и
ждем пока счетчик в драйвере привязанный на IRP_MJ_CREATE/IRP_MJ_CLOSE не обнулится. (по обнулению в драйвере можно выставить событие чтобы не было лишнего ожидания)
IRP_MN_QUERY_REMOVE_DEVICE/IRP_MN_SURPRISE_REMOVAL приходят в системной нити, поэтому все пользовательские процессы работают.

пользовательский процесс получает WM_DEVICECHANGE  и производит деинициализацию и CloseHandle для устройства. как только последний handle будет закрыт, ожидание в драйвере завершится и он сможет перейти к обработке IRP_MN_REMOVE_DEVICE, по которому удалить само устройство IoDeleteDevice().
минусы метода как и для первого - масса функций ожидания обработки WM_DEVICECHANGE всеми подключенными процессами.

3. метод подстмотрен в книжке W. Oney. заключается в том что каждое приложение запускает отдельную нить, в которой вызывает специальный DeviceIoControl() драйверу. драйвер этот IOCTL помечает как PENDING. Перед тем как внезапно удалить устройство - он завершает данный IOCTL, таким образом происходит синхронизация удаления.
мне такой подход не очень понравился, но как метод - почему бы и нет? может для чего то и можно применить...

и в четвертых - в 98 был еще один метод описываемый W. Oney, но я его не рассматривал по понятным причинам.

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


Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines