- •Лекция №7-8. Подсистема в/в. Пакеты запросов ввода/вывода (irp). [7.1] Подсистема в/в и её характеристики.
- •[7.2] Структура irp
- •[7.2.1] Поля в Фиксированной части irp.
- •[7.2.2.] Поля в Стеке размещения Ввода - вывода irp.
- •[7.3] Описание Буфера Данных
- •[7.4] Коды Функции Ввода - вывода
- •[8.1] Передача данных посредством irp и диспетчерские точки входа драйвера
- •[8.1.1] Запросы чтения и записи irp_mj_read и irp_mj_write [8.1.1.1] Определение метода передачи буфера для запросов чтения-записи
- •[8.1.1.2] Получение буфера
- •[8.1.1.3] Завершение запроса в/в
- •[8.1.1.4] Пример обработки запросов чтения/записи
- •[8.1.2] Irp_mj_device_controLиIrp_mj_internal_device_control [8.1.2.1] Пояснения по использованию
- •[8.1.2.2] Задание кода управления вводом/выводом (ioctl)
- •[8.1.2.3] Получение буфера
- •[8.1.2.4] Завершение запроса в/в
- •[8.1.2.5] Пример обработки
[8.1.1.3] Завершение запроса в/в
Для завершения запроса IRP на чтение/запись, необходимо установить поле Irp->IoStatus.Information равным числу прочитанных/записанных в буфер байт. В случае буферизованного в/в это поле укажет Диспетчеру в/в, сколько байт нужно скопировать из промежуточного буфера в невыгружаемой области системного адресного пространства в пользовательский буфер.
[8.1.1.4] Пример обработки запросов чтения/записи
Пример обработки запросов чтения/записи. Получение адреса буфера для чтения/записи и его длины. Такой код вставляется в обработчик диспетчерских функций MajorFunction[IRP_MJ_READ], MajorFunction[IRP_MJ_WRITE].
//получение адреса буфера для чтения/записи
//в случае буферизованного в/в
BufferAddress = Irp->AssociatedIrp.SystemBuffer;
//в случае прямого в/в
BufferAddress = MmGetSystemAddressForMdl( Irp->MdlAddress );
//вслучаеNeither i/o
BufferAddress = Irp->AssociatedIrp.UserBuffer;
//получение длины буфера для чтения/записи
stack = = IoGetCurrentIrpStackLocation( Irp );
BufferLength = stack->Parameters.Read.Length;
[8.1.2] Irp_mj_device_controLиIrp_mj_internal_device_control [8.1.2.1] Пояснения по использованию
Как говорилось выше, точка входа драйвера IRP_MJ_DEVICE_CONTROL вызывается при вызове пользовательской программой функции DeviceIoControl(). Прототип этой функции показан на рис.:
BOOL DeviceIoControl(
HANDLE hDevice, // описатель открытого устройства
DWORD dwIoControlCode, // контрольный код запрашиваемой операции
LPVOID lpInBuffer, // адрес буфера со входными данными
DWORD nInBufferSize, // размер входного буфера
LPVOID IpOutBuffer, // адрес буфера для приема выходных данных
DWORD nOutBufferSize, // размер выходного буфера
LPDWORD IpBytesReturnedy // адрес переменной для получения числа реально
// переданных байтов данных
LPOVERLAPPED IpOverlapped // адрес структуры для обеспечения асинхронности в/в
);
Рис. .Прототип функции DeviceIoControl().
Зачемнуженirp_mj_device_control?Когда драйвер поддерживает определенный тип устройства, такое устройство обычно имеет набор специализированных возможностей, которые могут управляться через драйвер. Эти возможности не могут быть задействованы использованием стандартных кодов функций irp_mj_create, irp_mj_close, irp_mj_read и irp_mj_write. Например, драйвер устройства для лентопротяжного устройства SCSI должен обеспечить механизм, который дает возможность пользователям послать запрос на стирание ленты. Такие зависящие от устройства запросы описываются, используя главный функциональный код irp_mj_device_control. Устройство обычно может принимать несколько разнотипных команд. Для драйвера тип такой команды указывается Кодом Управления ввода-вывода (IOCTL), который передается как часть запроса в/в.
Возвращаясь к функции DeviceIoControl(), код управления в/в (IOCTL) указывается во втором параметре этой функции. Код управления в/в имеет специальный формат, указывающий метод передачи буфера и другую информацию. Этот формат будет рассмотрен в следующем разделе.
Путаница может возникнуть при задании буфера для в/в. Как видно из прототипа функции DeviceIoControl(), она может передавать 2 буфера (3 и 5 параметры). Несмотря на названия буферов – входной и выходной буфер – выходной буфер может быть использован как для передачи данных в драйвер, так и для приема данных из драйвера. Разница будет в используемом методе передачи буфера. Использование буферов будет подробно рассмотрено в разделе “Получение буфера”.
