ArticleDirectory
- Threaded IRP
- Non-threaded IRP
- IRP creation Function
In the IO model of the NT kernel, there are two types of IRPs: threaded IRP and non-threaded IRP. As the name suggests, the former is bound to the thread, and the latter is irrelevant to the thread. When a threaded IRP is created, the creation thread will have a queue to save the IRP until the IRP is complete. When you try to exit this thread, the system will check the queue to see if there is still IRP in it. If yes, the thread will wait until all IRPs are completed. The non-thread IRP is the opposite. If the IRP has been returned to the place where it was created and you continue to complete it, bsod will occur.
Threaded IRP
As mentioned above, threaded IRP is bound with the thread. When the user mode Program initiates an IO operation (such as the writefile function), or one driver initiates an IO operation (such as zwwritefile) to another driver ), iomanager first finds the driver stack corresponding to the handle file, obtains the pdevice_object at the top of the stack, generates an IRP, and puts various information about Io operations into the IRP, put the IRP into the thread's IRP queue, and call iocalldriver to transfer the IRP to the driver stack for processing at each layer, the pointer in io_stack_location will move down a position (the actual situation is a little more complicated than this. Later, we will think of it as a stack, and each layer is pushed once ), it will not be returned until the hardware has been processed. The returned process is the opposite of the preceding one. After processing the IRP at the last layer, iocompleterequest is called. This function moves the io_stack_location pointer up (POP) and finally calls the completroutine set by the upper-layer driver. After the completeroutine of each layer completes the corresponding work, it will call iocompleterequest to continue the upward conversion of the IRP until the top of the stack pdevice_object. At this time, io_stack_location is already on the top, and the so-called completeroutine on the upper layer does not exist. Therefore, operations in the completeroutine on the current layer return the IRP to iomanager, and iomanager recycles resources, and remove the corresponding items from the thread IRP queue.
This process is very similar to function calling. As you will all ask: why does function calling and return not support stack-out operations, why don't we use this mechanism, instead, we need to build a separate set of machines. The answer is simple, that is, efficiency. The IO operations of the NT kernel are all asynchronous. The thread that calls iocalldriver and the response thread of completeroutine are not necessarily the same. We will talk about this later, but it raises a question that we need to care about now: Since the completerotine thread environment may have been switched, so how does iomanager know from which thread's IRP queue to remove corresponding items? The answer is also very simple, that is, stored in IRP. Every threaded IRP's pirp-> thread domain stores its creation thread. iomanager uses it to find the thread. Note: Some people may want to obtain information about the current thread from pirp-> thread, which is not correct.
Non-threaded IRP
Non-threaded IRP is generally created by the driver rather than iomanager. The thread does not store its instance in the IRP queue, and its pirp-> thread is null. When completeroutine returns all the data to the creator of the IRP, do not return the data to iomanager. You can simply drop it free.
IRP creation Function
The IRP from user mode must be threaded IRP, which is obvious. In kernel-State functions, which are threaded IRPs and non-threaed IRPs? The following table lists the functions:
Non-threaded |
Threaded |
Ioallocateirp |
Iobuildsynchronousfsdrequest |
Iobuildasynchronousfsdrequest |
Iobuilddeviceiocontrolrequest |
|
Tdibuildinternaldevicecontrolirp |
Here is a special case: iomakeassociatedirp, which is a non-threaded IRP, but you cannot directly free it, or call iocompleterequest to let its supervisor IRP release.