Форум программистов, компьютерный форум, киберфорум
Программирование драйверов
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.60/5: Рейтинг темы: голосов - 5, средняя оценка - 4.60
0 / 0 / 0
Регистрация: 12.02.2015
Сообщений: 10
1

Некорректное использование мьютекса

02.05.2015, 18:18. Показов 847. Ответов 1
Метки нет (Все метки)

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

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
NTSTATUS DriverFilter(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
    DbgPrint("I am in DriverFilter");
 
    PDEVICE_EXTENSION DevExt = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
    DevExt->PMutex = &Mutex;
 
    PDEVICE_EXTENSION DeviceExtension;
    NTSTATUS Status;
 
    PIO_STACK_LOCATION StackLocation = IoGetCurrentIrpStackLocation(Irp);
    PIO_STACK_LOCATION NextStackLocation = IoGetNextIrpStackLocation(Irp);
 
    *(NextStackLocation) = *(StackLocation);
 
    DeviceExtension = (PDEVICE_EXTENSION)(DeviceObject->DeviceExtension);
 
    IoSetCompletionRoutine(Irp, CompleteRequest, FilterDevice, TRUE, TRUE, TRUE);
 
    Status = IoCallDriver(DeviceExtension->TargetDeviceObject, Irp);
    
    return Status;
}
Далее, насколько я понимаю, вызывается драйвер нижележащего уровня. После работы всех драйверов нижележащего уровня запрос возвращается в функцию:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
NTSTATUS CompleteRequest(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
{
    DbgPrint("I am in CompleteRequest");
 
    PEPROCESS CurrentProcess = PsGetCurrentProcess();
    DbgPrint("%x", CurrentProcess);
    
    PKEYBOARD_INPUT_DATA KeyboardInformation = (PKEYBOARD_INPUT_DATA)Irp->AssociatedIrp.SystemBuffer;
    USHORT Key = KeyboardInformation->MakeCode;
 
    //--------Создаем поток для работы с файлом------------//   
    //USHORT* Ptemp = &Key;
    MyCONTEXT _Context;
    _Context.Key = Key;
    _Context.Mutex = Mutex;
    MyPCONTEXT _PContext = &_Context;
 
    NTSTATUS Status = PsCreateSystemThread(&ThredHandle, 0, NULL, 0, NULL, WorkWithFile, (PVOID)(_PContext));
    if (Status == STATUS_SUCCESS)
    {
        DbgPrint("I create Thred!");
    }
 
    else DbgPrint("I cant create thread");
    
    if (Irp->PendingReturned)
        IoMarkIrpPending(Irp);
 
    ZwClose(ThredHandle);
 
    return STATUS_SUCCESS;
}
Содержимое функции WorkWithFile:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
VOID WorkWithFile(PVOID Context)
{
    MyPCONTEXT Data = (MyPCONTEXT)Context;  
 
    DbgPrint("I am in new thread!");
 
    ULONG UGoodLenght;
    size_t SGoodLenght;     
 
    //----------Открываем файл----------------//
    RtlInitUnicodeString(&FileName, L"\\DosDevices\\C:\\PressKey.txt");
    InitializeObjectAttributes(&ObjectAttributes, &FileName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
 
    NTSTATUS Status = ZwCreateFile(&HandleFile, FILE_APPEND_DATA, &ObjectAttributes, &StatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
    if (Status != STATUS_SUCCESS)
    {
        DbgPrint("I can't open file");
        PsTerminateSystemThread(STATUS_SUCCESS);
    }
    else
    {
        DbgPrint("I open file! Descriptor = %x", HandleFile);
        FileIsOpen = TRUE;
    }
    //------------------------------------//
 
    CHAR Buffer[100];
 
    USHORT temp = Data->Key;
 
    DbgPrint("I have key = %x", temp);
    Status = RtlStringCbPrintfA(Buffer, sizeof(Buffer), "%x ", temp);
    if (Status != STATUS_SUCCESS)
    {
        DbgPrint("Error in RtlStringCbPrintfA = %x", Status);
        PsTerminateSystemThread(STATUS_SUCCESS);
    }
 
    Status = RtlStringCbLengthA(Buffer, sizeof(Buffer), &SGoodLenght);
    if (Status != STATUS_SUCCESS)
    {
        DbgPrint("Error in RtlStringCbLengthA = %x", Status);
        PsTerminateSystemThread(STATUS_SUCCESS);
    }
 
    UGoodLenght = (ULONG)(SGoodLenght);
    IO_STATUS_BLOCK StatusBlock2;
    
    Status = ZwWriteFile(HandleFile, NULL, NULL, NULL, &StatusBlock2, Buffer, (ULONG)SGoodLenght, NULL, NULL);
    if (Status != STATUS_SUCCESS)
        DbgPrint("I can't write in file.");
 
    ZwClose(HandleFile);
    HandleFile = NULL;
    
    PsTerminateSystemThread(STATUS_SUCCESS);
}
Пробовал работать с мьютексом следующим образом:
1) При работе с функцией WorkWithFile использовал глобальный мьютекс при помощи ф-и KeWaitForMutexObject, освобождал мьютекс при помощи функции KeReleaseMutex. Появлялся BSOD, ругался на некорректный мьютекс.
2) Ф-ю KeWaitForMutexObject использовал в функции DriverFilter, ф-ю KeReleaseMutex использовал в CompleteRequest. Функция KeWaitForMutexObject отрабатывалась отлично, но при освобождении мьютекса появлялась та же самая ошибка. В чем я не прав?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
02.05.2015, 18:18
Ответы с готовыми решениями:

Некорректное использование переменной PHP в запросе к базе данных MySQL
Я ещё совсем зелёный в веб-программировании, на днях решил сделать сайт тестирования знаний по ПДД....

Освобождение объекта мьютекса
Подскажите почему не получается освободить объект мьютекса? HANDLE hx; void __fastcall...

Таски и захват мьютекса
Перешел с одного компа на другой - получил проблему. Использую таски. Таски по очереди...

Guard для мьютекса
Собственно нужно написать гвард для мьютекса. Если я правильно понимаю, в конструкторе нужно...

1
Ушел с форума
Эксперт С++
16478 / 7441 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
02.05.2015, 18:52 2
Не обижайтесь, но этот код - ужас-ужас-ужас.
Здесь неправильно почти все. Из того, что сразу бросается в глаза:

1. Перед установкой completion routine нужно вызвать функцию
IoCopyCurrentStackLocationToNext,сдвигая IO_STACK_LOCATION на
нужную позицию. Это более четкий вариант, чем то, что творится в
строках 11-14.

2. Completion Routine может вызываться на IRQL <= DISPATCH_LEVEL,
поэтому ни PsCreateSystemThread, ни ZwClose там вызывать нельзя.

3. Вместо того, чтобы на каждое нажатие создавать отдельный
поток (или work item), лучше сразу сделать его где-нибудь в
DriverEntry и пускай крутится в ожидании.

4. В Completion Routine нужно проверять IoStatus.Status.

5. В Completion Routine структура _Context локальная, она
может перестать существовать на тот момент, когда поток
дойдет до ее чтения (возможно, из-за этого и BSOD).

6. PsTerminateSystemThread не нужен, достаточно просто
выйти из функции потока.

Как бы я сделал:

1) В DriverEntry создал бы отдельный фоновый поток и
какую-нибудь очередь, защищенную спин-локом.

2) Когда срабатывает completion routine, захватываем
спин-лок, добавляем скан-коды в очередь, освобождаем
спин-лок, сигнализируем потоку, что есть новые данные.

3) Поток не спеша выгребает данные из очереди и скидывает
их в файл.
1
02.05.2015, 18:52
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
02.05.2015, 18:52
Помогаю со студенческими работами здесь

Странное поведение мьютекса
Имеется такой кусок кода Mutex instanse; bool is_new; ...

Sleep внутри мьютекса
Может ли это как-то вешать программу, если да то почему?

Реализовать обработку сообщений с помощью мьютекса
Всем привет! Нужно код на задачу с помощью мьютекса! Может у кого нибудь есть?? :-[ Производители...

Организовать синхронизацию процессов с поддержкой семафора и мьютекса
Здравствуйте. Задача: Организовать синхронизацию процессов с помощью семафора и мьютекса....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
2
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru