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

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Очередь IRP управляемая драйвером  (Прочитано 7169 раз)
0 Пользователей и 1 Гость смотрят эту тему.
vladsizov1
Гость
« : 24-09-2003 05:17 » 

не  подскажет ли кто  ссылку  как создавать очереди  IRP управляемую  драйвером  . Мой  фильтр  находится  над SERIAL.SYS
принимает  сверху  пакет   и передает  вниз   ,а  снизу  принимает,
собирает в пакет  и передает  наверх  ,  причем  работа с устройством
должна быть в дуплексе ,  то  есть видимо должны быть две
очереди  на чтение  и запись  ,мне не ясно ,что ? нужно создавать
два потока  для чтения и записи   и как синхронизация при выборке и
помещении в очередь  ?  может  кто пример  покажет ?
Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #1 : 24-09-2003 07:37 » 

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

struct Irp_Container
{
LIST_ENTRY ListEntry;
PIRP Irp;
};

создаешь два события

KEVENT                  global_ReadEvent;
KEVENT                  global_WriteEvent;

инициализируешь их до первого использования

KeInitializeEvent(&global_ReadEvent,SynchronizationEvent,FALSE);
KeInitializeEvent(&global_WriteEvent,SynchronizationEvent,FALSE);

создаешь заголовки двух очередей

LIST_ENTRY              global_read_list;
LIST_ENTRY              global_write_list;

также инициализируешь до первого использования

InitializeListHead(&global_read_list);
InitializeListHead(&global_write_list);

создаешь спин блокировки для блокирования доступа к спискам

KSPIN_LOCK  global_SpinLockRead;
KSPIN_LOCK  global_SpinLockWrite;

также инициализируешь до первого использования

KeInitializeSpinLock(&global_SpinLockRead);
KeInitializeSpinLock(&global_SpinLockWrite);

Делаешь ф-ции потоков(показываю только одну)

VOID ReadIrpThread (IN PVOID Context)
{
    PLIST_ENTRY                  request;
    PIRP                              pIrp;
    Irp_Container*               pReadIrp ;
         
    KeSetPriorityThread(KeGetCurrentThread(),LOW_REALTIME_PRIORITY);
   
    while (TRUE)
    {
        KeWaitForSingleObject(&global_ReadEvent,Executive,KernelMode,FALSE,NULL);
      
      while (request = ExInterlockedRemoveHeadList(&global_read_list,&global_SpinLockRead))
      {
                                   pReadIrp= CONTAINING_RECORD(request,Irp_Container,ListEntry);
                                    pIrp = pReadIrp->Irp;
                                   ...................................................
                                   тут обрабатываешь Irp
                                 }
  if (InterlockedCompareExchange(&global_TerminateReadThread,0,0))
    {
            dprintf("Terminating Thread\n");
            PsTerminateSystemThread(STATUS_SUCCESS);
    }

    }

  }

в драйвере  помещаешь IRP в очередь и савишь event в сигнальное состояние, поток проснется и вынет его из очереди и обработает. Память под структуру Irp_Container выделяй из неподкачиваемого пула и не забывай освобождать после того как из очереди в потоке обработки вынешь. Вот как помещать в очередь

Irp_Container* pIrpContainer;
pIrpContainer = ExAllocatePool(NonPagedPool,....);
pIrpContainer->Irp=Irp;

ExInterlockedInsertTailList(&global_read_list,&pIrpContainer->ListEntry,&global_SpinLockRead);
       
// Sending Event to ReadIrpThread   
KeSetEvent(&g_AccessThreadEvent,(KPRIORITY)0,FALSE);

Для остановки потока ставишь переменную  global_TerminateReadThread в и 1 переводишь событие в сигнальное состояние.
Потоки создаешь при помощи PsCreateSystemThread.
Продумай, что ты будешь делать после откладывания IRP на обработку- возваращать STATUS_PENDING или блокировать и ждать обработки этого IRP.
Есть еще системные очереди, но я их не использую.
И подумай насколько тебе нужны очереди, может и без них можно?
Записан
vladsizov1
Гость
« Ответ #2 : 30-09-2003 01:09 » 

слава  а может  такое  случится , что  пока  я обрабатываю  большой  пакет
мне  в  очередь  натолкают  много   мелких   в  результате я  словлю
event  на   самый  последний  и из-за  этого  очередь  постоянно  будет
распухать ?
Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #3 : 30-09-2003 05:35 » 

Цитата

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


Внимательно смотри на код- я в цикле вынимаю все пакеты в очереди, после того как получу event, если придут event от уже вынутых пакетов и очередь пуста, то  ExInterlockedRemoveHeadList вернет NULL. То есть получив хоть один event я освобождаю всю очередь. Очередь никогда не распухнет.
Этот код работает всегда даже в очень загруженной системе. Проверено на фильтрах USB, файловых систем, сетевых карт.
Записан
SlavaI
Главный специалист

ru
Offline Offline

« Ответ #4 : 30-09-2003 05:52 » new

Еще раз обращу внимание на такой момент- тебе надо как-то уведомить верхний драйвер, что обработка IRP отложена. Если уровень IRQL<DISPATCH то можно заблокировать поток до обработки IRP, или можно не блокировать(что намного лучше и единственно возможно при IRQL>=DISPATCH) и вернуть STATUS_PENDING, не забыв перед постановкой IRP в очередь пометить его как запенденный то есть

IoMarkIrpPending(Irp);
ExInterlockedInsertTailList(&global_read_list,&pIrpContainer->ListEntry,&global_SpinLockRead);
..............................
return STATUS_PENDING;
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines