49. Windows Driver Model Design Notes (7), IRP

Source: Internet
Author: User

I. IRP

The mdladdress (pmdl) domain points to a memory Descriptor Table (MDL), which describes a user mode buffer associated with the request. If the flags field of the top-level device object is do_direct_io, the I/O manager is irp_mj_read or irp_mj_write request to create this MDL. If the control of an irp_mj_device_control requestCodeIf the method_in_direct or method_out_direct operation mode is specified, the I/O manager creates an MDL for the output buffer used by the request. MDL is used to describe the user mode virtual buffer, but it also contains the physical address of the buffer to lock the Memory Page.

The associatedirp (union) field is a three-pointer union. Among them, with the WDM DriverProgramThe related pointer is associatedirp. systembuffer. The systembuffer Pointer Points to a data buffer in non-Paging memory in kernel mode. For irp_mj_read and irp_mj_write operations, if the top-level device specifies the do_buffered_io flag, the I/O manager creates the data buffer. For the irp_mj_device_control operation, if the I/O Control Function Code specifies that a buffer is required, the I/O manager creates the data buffer. The I/O manager copies the data that the user mode program sends to the driver to this buffer zone, which is part of the IRP creation process. The data can be the data related to the writefile call, or the so-called input data in the deviceiocontrol call. For read requests, the device driver fills in the read data in the buffer zone, and then the I/O manager copies the buffer content to the user mode buffer zone. For I/O control operations that specify method_buffered, the driver puts the so-called output data in this buffer, and then the I/O manager copies the data to the output buffer in user mode.

Iostatus (io_status_block) is a structure that contains only two fields. The driver sets this structure when the request is finally completed. Iostatus. the Status field will receive an ntstatus code, while the iostatus. the type of information is ulong_ptr, which receives an information value. the exact meaning of this information value depends on the specific IRP type and the request Completion status. An accepted use of the information domain is to save the total traffic for data transmission operations, such as irp_mj_read. Some PNP requests use this field as a pointer to another structure, which usually contains the query request results.

Userbuffer (pvoid) for the irp_mj_device_control request in method_neither mode, this field contains the user mode virtual address of the output buffer. This domain is also used to save the user mode virtual address of the read/write request buffer, but the driver with the do_buffered_io or do_direct_io flag is specified, and its read/write routines usually do not need to access this domain. When processing a method_neither control operation, the driver can use this address to create its own MDL.

Tail. overlay is a structure in the tail union. It contains several potential users of the WDM driver. The figure below is a combination of tail. In this figure, from left to right in the horizontal direction is the Three Optional members of the Union, and the vertical direction is the member description of each structure. Tail. Overlay. devicequeueentry (kdevice_queue_entry) and tail. Overlay. drivercontext (pvoid [4]) are two optional members (only one member can appear) that are not named in tail. overlayare ). The I/O manager uses devicequeueentry as the connection domain in the device standard request queue. When the IRP has not entered a queue, you can use this field if you own this IRP. You can use four pointers in drivercontext at will. Tail. Overlay. listentry (list_entry) can only be used as the connection domain of your own private queue.

Ii. Io Stack

When any kernel mode program creates an IRP, it also creates an io_stack_location structure array associated with it: each stack unit in the array corresponds to a driver that will process the IRP, there is also a stack unit for the IRP creator. The stack unit contains the type code and parameter information of the IRP and the address of the completed function.

Graphical representation of the parallel relationship between the driver and the I/O Stack

FigureDisplay.I/OStack Unit Data Structure

Majorfunction (uchar) is the primary function code of the IRP. This code should be the same value as irp_mj_read and correspond to a dispatch function pointer in the majorfunction table of the driver object.

Minorfunction (uchar) is the sub-function code of the IRP.

Parameters (union) is the union of several sub-structures. Each request type has its own special parameters, and each sub-structure is a parameter. These sub-structures include create (irp_mj_create request), read (irp_mj_read request), and startdevice (irp_mj_pnp irp_mn_start_device sub-type.

Deviceobject (pdevice_object) is the address of the device object corresponding to the stack unit. This field is filled by the iocalldriver function.

Fileobject (pfile_object) is the address of the kernel file object, and the IRP object is the file object. The driver usually uses the fileobject pointer when processing the clear request (irp_mj_cleanup) to distinguish IRP irrelevant to the file object in the queue.

Completionroutine (pio_completion_routine) is the address of an I/O completion routine. This address is set by the driver corresponding to this stack unit, which is a higher-level driver. You must never directly set this field. You should call the iosetcompletionroutine function, which knows how to refer to the stack unit of the next driver. The lowest-level drivers of the device stack do not need to complete the routine because they must directly complete the request. However, the request initiator sometimes needs a completion routine, but usually does not have its own stack unit. This is why each level-1 driver uses the stack unit of the next level driver to save its own complete routine pointer.

Context (pvoid) is an arbitrary context-related value and is passed as a parameter to the completion routine. You must never directly set this field. It is automatically set by the iosetcompletionroutine function and its value comes from a parameter of this function.

FigureDisplayStandard Model for. IRP Processing"

1. Create

You can use any of the following functions to create IRP:

• Iobuildasynchronousfsdrequest creates an asynchronous IRP (you do not need to wait for it to complete ). This function and the next function are only applicable to creating certain types of IRPs.

• Iobuildsynchronousfsdrequest ).

• Iobuilddeviceiocontrolrequest creates a synchronous irp_mj_device_control or irp_mj_internal_device_control request.

• Ioallocateirp creates IRPs of other types not supported by the preceding three functions.

2. Dispatch routine

After the IRP is created, you can call iogetnextirpstacklocation to obtain the pointer of the first stack unit of the IRP. Then initialize the stack unit. At the end of the initialization process, you need to fill in the majorfunction code. After the stack unit Initialization is complete, you can call the iocalldriver function to send the IRP to the device driver:

Pdevice_object deviceobject; // something gives you this

Pio_stack_location stack = iogetnextirpstacklocation (IRP );

Stack-> majorfunction = irp_mj_xxx;

<Other initialization of "stack">

Ntstatus status = iocalldriver (deviceobject, IRP );

The first parameter of the iocalldriver function is the address of the device object you obtained somewhere.

The first stack unit pointer in IRP is initialized to the stack unit before it points to the stack unit, because the I/O stack is actually an array of the io_stack_location structure, you can think that this pointer is initialized to point to a non-existent "-1" element. Therefore, when we want to initialize the first stack unit, what we actually need is "Next" stack unit. Iocalldriver will find 0th table items along the stack pointer, and extract the main function code we put there, irp_mj_xxx in the above example. The iocalldriver function then uses the driverobject pointer to find the majorfunction table in the device object. Iocalldriver uses the main function code to index the table, and finally calls the found address (dispatch function ).

Ntstatus iocalldriver (pdevice_object device, pirp)

{

Iosetnextirpstacklocation (IRP );

Pio_stack_location stack = iogetcurrentirpstacklocation (IRP );

Stack-> deviceobject = device;

Ulong FCN = stack-> majorfunction;

Pdriver_object driver = device-> driverobject;

Return (* driver-> majorfunction [FCN]) (device, IRP );

}

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.