Asynchronous I / O Is A Mechanism Through Which A Calling Thread Can Submit An I / O Request And Return Before The Submitted Request Gets Served by The Kernel.
There Are Four Way by Which The Calling Thread Can Know The Status and Result of The Submitted Asynchronous I / O Request:
Event Object: You can set an EVENT object to the overlapped structure, then pass this overlapped structure to a READFILE or WRITEFILE function to operate the IO object opened in file_flag_overlapped. When the IO request is completed, the EVENT object in the Overlapped structure will signal, and any waiting function is released, and the I / O object can be handled synchronously. This method provides a lot of flexibility for multiple threads to perform IO operations, because different threads can wait for an event object corresponding to each submitted (ie, completed) IO operation in the Overlapped structure. In this case, the thread needs to call the WATXXX APIS to obtain the status of the submitted I / O request.
Using File Object: The thread can wait for the completion IO operation that is submitted by the file handle. This method has a drawback that an application starts two I / O operations on the same file handle, the application cannot determine that completion I / O has completed the panelable file handle SIGNALED. In this case, the thread also needs to wait for the completion of the IO request.
GetOverlappedResult: You can call this function, you can use the waiting function (set to true). Use event EVENT objects in the Overlapped structure that makes the function. If the HEVENT member in the Overlapped structure is NULL, the kernel will signal the Signaled HFile object after the IO operation is submitted.
The IO Completion Port: IO completion port is a kernel object that can be associated with multiple IO objects (such as file pairs, sockets or pipes). When an asynchronous operation is started on an IO object that has been associated with the IO Completion port, the calling thread will return immediately. After a submitted IO request is completed, the core will deliver the completion packet to the queue associated with the completion port.
Windows introduces IO completion ports The purpose of the port is to implement a structure that can be more suitable for the service application: the service application should be able to use a limited thread to serve multiple clients, which integrates the thread pool. The number of these threads depends on the number of processors. An IO completion port and asynchronous IO operation can be bundled to implement an extensible service application.
The CreateioCompletionPort function is used to associate an IO object with one IO completion port. When an IO operation is executed on a IO object associated with the IO completion port, the kernel IO system is sent to the queue associated with the IO completion port after the submitted IO request is completed. The working thread in the thread pool is waiting for the GetQueueCompletionStatus function waiting for the IO to complete the port (status).
The thread that is blocked on the IO completion port will be released in a LIFO manner, which is the most suitable way of service application architecture because it can reduce the context switch, which is the basic feature of the service application design. Once the worker thread completes the processing of the IO completion message in the queue, the thread calls the getQueueCompletionStatus function to get and process the next IO completion message. If there is no message in the queue, the thread will be shaped and waiting for the packet to assign the IO to complete the port. This is the beauty and power of the IO Completion Port, because less context switch, higher efficiency provides easy performance performance, so that the server can withstand greater loads. Because Call getQueueCompletionStatus can always retrieve the IO completion packets in the queue, the worker thread will not be blocked, so that the context switch can be reduced.
The kernel will control the number of running threads associated with the IO Completion Port, making it not more than the concurrent restriction of the IO Completion Port. The control method used by the kernel is to block the thread that call the getQueueCompletionStatus function until the number of running threads associated with the port is lower than the concurrent limit set when creating Port.
When a getQueueCompletionStatus returns, only the IO request on a IO object has been completed, the service application needs to determine that this IO request is done on that IO object, this important information is to return to the caller by the Key parameter of the getQueueCompletionStatus function. This Key value is specified to complete port when the IO completion is associated with an IO object. If this Key is understood, it depends on the service application itself, the service application can use this key to uniquely identify in a customer information array. A customer information record.