Двусвязные списки в драйвере

Тема в разделе "WASM.NT.KERNEL", создана пользователем DoZENT, 12 мар 2007.

  1. DoZENT

    DoZENT New Member

    Публикаций:
    0
    Регистрация:
    12 мар 2007
    Сообщения:
    50
    Постепенно начинает проясняться) Такой еще вопрос: KeAcquireSpinLock и KeReleaseSpinLock когда надо юзать? Как я понял, при добавлении в лист элементов, удаления из него?
     
  2. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    Можно и так :P
    При любом доступе к элементу.
     
  3. DoZENT

    DoZENT New Member

    Публикаций:
    0
    Регистрация:
    12 мар 2007
    Сообщения:
    50
    А вот у меня так не получилось( Как n0name сказал работает)
     
  4. DoZENT

    DoZENT New Member

    Публикаций:
    0
    Регистрация:
    12 мар 2007
    Сообщения:
    50
    Делаю так:
    Код (Text):
    1.     POBJECTSLIST TempList;
    2.     KIRQL oldKIRQL;
    3.  
    4.    
    5.    
    6.     DPRINT ("Adding item....%S\n",ObjectData.DirPath);
    7.     KeAcquireSpinLock (&ListSpinLock, &oldKIRQL);
    8.     TempList = ExAllocatePool (NonPagedPool,sizeof(POBJECTSLIST));
    9.     if (!TempList)
    10.     {
    11.         KeReleaseSpinLock (&ListSpinLock, oldKIRQL);
    12.         DPRINT ("Can't allocate memory for TempList!");
    13.         return;
    14.     }
    15.  
    16.     TempList->bod = ObjectData;
    17.  
    18.      
    19.         ExInterlockedInsertTailList(&ListHead, &TempList->ListEntry, &ListSpinLock);
    20.     KeReleaseSpinLock (&ListSpinLock, oldKIRQL);
    Копм виснет. Если убрать KeAcquireSpinLock и KeReleaseSpinLock, все нормально работает, если добавлять элементы редко (1-2 раза в секунду). Если чаще, то тоже виснет (что в приципе понятно). Почему не работает связка KeAcquireSpinLock и KeReleaseSpinLock?

    З.Ы. KeInitializeSpinLock (&ListSpinLock); сделал в DriverEntry.
    З.З.Ы. Надо ли здесь освобождать TempList?
     
  5. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    Вот это совершенно лишняя команда.
    Либо блокаешь вручную KeAcquireSpinLock/KeReleaseSpinLock. Либо за тебя всё сделает ExInterlockedInsertTailList.
    Нет.
     
  6. DoZENT

    DoZENT New Member

    Публикаций:
    0
    Регистрация:
    12 мар 2007
    Сообщения:
    50
    Как лишняя?? Это же вставка нового элемента в лист. Или я что-то не так понял? Может надо юзать InsertHeadList?

    Как вручную?

    Вряд ли, если оставить все без KeAcquireSpinLock и KeReleaseSpinLock, то копм виснет, т.е. как я понимаю, блокировка не происходит.
     
  7. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    Тебе что конкретно надо от синхронизации? Обеспечить корректную работу в МП системе? Или дать только одному потоку доступ к списку в однопроцессорной системе?
    В кратце: она вставляет элемент в двусвязный список. Нужна для синхронизации в мультипроцессорной среде(HT, 2-4ядерники, SMP).
    Если ты не хочешь париться с МП, то лучше юзай мьютексы. Они как раз и предназначены предоставлять доступ к ресурсу только одному потоку в промежуток времени. То есть "одновременно" не может быть такого, что один поток читает из памяти, а другой пишет туда.
     
  8. DoZENT

    DoZENT New Member

    Публикаций:
    0
    Регистрация:
    12 мар 2007
    Сообщения:
    50
    OK, мне надо реализовать следующее. У меня есть список файлов, к которым доступ запрещен. Я перехватываю API функцию (допустим NtOpenFile). Получаю имя открываемого файла. Теперь мне надо вызвать что-то типа IsAdded (...). Если этот файл в списке, то вернуть STATUS_ACCESS_DENIDED. Если не в списке, то вызвать оригинальню функцию. Так вот, вызов NtopenFile в системе происходит очень часто, поэтому может получиться так, что одна IsAdded еще не выполнилась, а ее вызывают еще раз. Что произойдет в этом случае? Ситуация еще хуже, если у компа 2 проца/1 проц, но 2-х ядерный. Собственно вопрос: как избежать зависания/падения системы в этом случае
     
  9. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    чтение не изменяет данных, так что с синхронизацией делать ничего не надо.
     
  10. DoZENT

    DoZENT New Member

    Публикаций:
    0
    Регистрация:
    12 мар 2007
    Сообщения:
    50
    Попробую, но несколько постов назад ты говорил:

    Я не так понял?
     
  11. DoZENT

    DoZENT New Member

    Публикаций:
    0
    Регистрация:
    12 мар 2007
    Сообщения:
    50
    Чтобы проблема была совсем понятной, привожу куски кода, которые мне необходимо написать. Что в них неправильно?

    Добавление в лист:
    Код (Text):
    1. void AddItem(LIST_ENTRY ListHeadToChange,PWSTR FileName)
    2. {
    3.  
    4.     POBJECTSLIST TempList;
    5.  
    6.    
    7.     DPRINT ("Adding item....%S\n",FileName);
    8.    
    9.     TempList = ExAllocatePool (NonPagedPool,sizeof(POBJECTSLIST));
    10.     if (!TempList)
    11.     {
    12.        
    13.         DPRINT ("Can't allocate memory for TempList! on AddItem");
    14.         return;
    15.     }
    16.  
    17.     TempList->FileName = FileName;
    18.  
    19.          InsertHeadList (&ListHead,&TempList->ListEntry);  
    20.  
    21. }
    Проверка на существование элемента:

    Код (Text):
    1. BOOLEAN IsAdded(PWSTR FileName)
    2. {
    3.  
    4.  
    5.     POBJECTSLIST TempList;
    6.     PWSTR FirstString;
    7.     PWSTR NextString = NULL;
    8.  
    9.  
    10.     TempList = ExAllocatePool (NonPagedPool,sizeof(POBJECTSLIST));
    11.     if (!TempList)
    12.     {      
    13.         DPRINT ("Can't allocate memory for TempList on IsAdded!");
    14.         return FALSE;
    15.     }
    16.    
    17.    
    18.  
    19.     __try
    20.     {
    21.        
    22.         TempList->ListEntry = ListHead;
    23.         FirstString = TempList->FileName;
    24.         DPRINT ("FirstString = %S", FirstString);
    25.         while (NextString != FirstString)
    26.         {
    27.             NextString = TempList->FileName;
    28.             DPRINT ("NextString = %S", NextString);
    29.  
    30.             if (pos (FileName,NextString))
    31.             {
    32.                
    33.                 return TRUE;
    34.  
    35.             }
    36.  
    37.             TempList->ListEntry = *ListHead.Flink;
    38.             NextString = TempList->bod.DirPath;
    39.  
    40.         }      
    41.  
    42.  
    43.  
    44.     }
    45.     __except (EXCEPTION_EXECUTE_HANDLER)
    46.     {
    47.        
    48.         DPRINT ("Exception on searching the same string\n");
    49.         return FALSE;
    50.  
    51.     }
    52.    
    53.  
    54.    
    55.     return FALSE;
    56.  
    57. }
    В отладчик выводится "Exception on searching the same string". "FirstString = ......" не выводится
     
  12. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    Я думал раз ты спрашивал про добавление элементов, то тебе надо будет и запись синхронизировать.
    sizeof(POBJECTSLIST) == sizeof(void *), то есть ты выделяешь память размером 4/8 байт. А тебе надо размер твоей структуры, а не указателя на неё.
    IsAdded:
    Зачем? У тебя же уже есть список элементов, пробегаешь по нему и всё.
    в общем исходник IsAdded абсолютно лишён смысла. Советую вначале прочитать про двусвязные списки.
     
  13. DoZENT

    DoZENT New Member

    Публикаций:
    0
    Регистрация:
    12 мар 2007
    Сообщения:
    50
    А как мне узнать какое количество элементов мне надо пробегать? Насколько я понял, элемент FLink структуры LIST_ENTRY указывает на следующий элемент, а последний FLink указывает на первый элемент (т.е. как бы по кругу).
     
  14. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    DoZENT
    да. тебе придется где-то сохранить первый указатель и выходить из этого круга, когда очередной указатель совпал с сохраненным первым.
     
  15. DoZENT

    DoZENT New Member

    Публикаций:
    0
    Регистрация:
    12 мар 2007
    Сообщения:
    50
    В общем не знаю даже, неделю с этими списками разираюсь(( Вот что сейчас наработал:

    AddItem:
    Код (Text):
    1. void AddItem(LIST_ENTRY ListHeadToChange,blockedObjectData ObjectData)
    2. {  
    3.  
    4.  
    5.     PDEVICE_EXTENSION TempList;
    6.  
    7.  
    8.     DPRINT ("Adding item....%S\n",ObjectData.DirPath);
    9.    
    10.  
    11.     TempList = ExAllocatePool (NonPagedPool,sizeof(DEVICE_EXTENSION));
    12.  
    13.     if (!TempList)
    14.     {      
    15.         DPRINT ("Can't allocate memory for TempList! on AddItem");
    16.         return;
    17.     }
    18.    
    19.  
    20.     TempList->str = ObjectData.DirPath;
    21.  
    22.     InsertHeadList (&pdx->ListHead,&TempList->ListHead);
    23.    
    24.  
    25. }
    AddItem вроде работает...

    IsAdded:
    Код (Text):
    1. BOOLEAN IsAdded(blockedObjectData bod)
    2. {
    3.  
    4.     PDEVICE_EXTENSION TempList;
    5.  
    6.  
    7.     DPRINT ("Checking item....%S\n",bod.DirPath);
    8.  
    9.  
    10.     TempList = ExAllocatePool (NonPagedPool,sizeof(DEVICE_EXTENSION));
    11.  
    12.     if (!TempList)
    13.     {      
    14.         DPRINT ("Can't allocate memory for TempList! on AddItem");
    15.         return FALSE;
    16.     }
    17.  
    18.  
    19.  
    20.     //TempList - самый первый элемент
    21.     TempList->ListHead = pdx->ListHead;
    22.  
    23.     if (!IsListEmpty (&TempList->ListHead))
    24.     {
    25.        
    26.         __try
    27.         {
    28.  
    29.             DPRINT ("%S\n", TempList->str);
    30.  
    31.  
    32.  
    33.             DPRINT ("Trying to free TempList...");
    34.             RemoveHeadList (&TempList->ListHead);
    35.             //KeReleaseSpinLock ()
    36.             DPRINT ("ok\n");
    37.         }
    38.         __except (EXCEPTION_EXECUTE_HANDLER)
    39.         {
    40.             return FALSE;
    41.             DPRINT ("\n");
    42.             DPRINT ("Exception on deleting TempList (in IsAdded)\n");
    43.         }
    44.  
    45.     }
    46.     else
    47.     {
    48.         DPRINT ("TempList is empty, nothing to free\n");
    49.     }
    50.  
    51.  
    52.  
    53.     return FALSE;
    54.  
    55. }
    А вот IsAdded на строке DPRINT ("%S\n", TempList->str); выдает ???????. Такая же фигня, если вместо текстовой переменной сделать int. Тогда выдает 0.
     
  16. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Ну а ты че хотел. Выделяешь память ExAllocatePool'ом, а потом сразу выводишь её на экран.
    Ты ожидаешь чего-то другого, кроме нуля?
     
  17. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    Зачем при пробеге ты выделяешь память?
     
  18. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    это кстати неизвестно:) он чего накосячил вообще со списками. кажется, он не понял их устройства..
     
  19. DoZENT

    DoZENT New Member

    Публикаций:
    0
    Регистрация:
    12 мар 2007
    Сообщения:
    50
    Если ее не выделять, то вываливается exception на TempList->ListHead = pdx->ListHead;

    Код (Text):
    1. BOOLEAN IsAdded(blockedObjectData bod)
    2. {
    3.  
    4.     PDEVICE_EXTENSION TempList = NULL;
    5.  
    6.  
    7.     DPRINT ("Checking item....%S\n",bod.DirPath);
    8.  
    9.  
    10.    
    11.     //TempList - самый первый элемент
    12.     TempList->ListHead = pdx->ListHead;
    13.  
    14.     if (!IsListEmpty (&TempList->ListHead))
    15.     {
    16.        
    17.         __try
    18.         {
    19.  
    20.             DPRINT ("%S\n", TempList->str);
    21.  
    22.  
    23.  
    24.             DPRINT ("Trying to free TempList...");
    25.             RemoveHeadList (&TempList->ListHead);
    26.             //KeReleaseSpinLock ()
    27.             DPRINT ("ok\n");
    28.         }
    29.         __except (EXCEPTION_EXECUTE_HANDLER)
    30.         {
    31.             return FALSE;
    32.             DPRINT ("\n");
    33.             DPRINT ("Exception on deleting TempList (in IsAdded)\n");
    34.         }
    35.  
    36.     }
    37.     else
    38.     {
    39.         DPRINT ("TempList is empty, nothing to free\n");
    40.     }
    41.  
    42.  
    43.  
    44.     return FALSE;
    45.  
    46. }
    да, я и не отрицаю, я не понял их устройства. Очень стараюсь понять, но пока безрезультатно. В сети/DDK/книгах море теории по этой теме, но практических примеров нигде не видел (кроме добавления/удаления элементов). Сделал так, как по моему мнению должно было работать. Не работает. Из-за этого встал весь проект.

    P.S. Заметьте, не прошу написать за меня эти функции, просто скажите, что в них неправильно?
     
  20. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    рекомендую выползти обратно в ринг3 на время и на простых программах разобраться со списками. Это очень важная информационная структура, с которой придется не раз встречаться еще. Чем раньше разберешься, тем лучше