2,I/O 完成端口 - Win32 apps | Microsoft Learn
通过阅读微软的I/O完成端口介绍,可以大致了解该机制通常结合异步I/O解决多线程的高并发问题。以scanner/user的代码为例,I/O完成端口的使用分为以下几步:
1,通过CreateIoCompletionPort将文件句柄与端口进行关联,并设置处理异步I/O业务的线程数
hr = FilterConnectCommunicationPort( ScannerPortName,
0,
NULL,
0,
NULL,
&port );//返回需要关联的文件句柄
if (IS_ERROR( hr )) {
printf( "ERROR: Connecting to filter port: 0x%08x\n", hr );
return 2;
}
//
// Create a completion port to associate with this handle.
//
//关联句柄,设置工作线程数量
completion = CreateIoCompletionPort( port,
NULL,
0,
threadCount );//工作线程数量
2,创建线程,等待处理I/O业务
while (TRUE) {
#pragma warning(pop)
//
// Poll for messages from the filter component to scan.
//
//
// 尝试从指定的 I/O 完成端口取消对 I/O 完成数据包的排队。 如果没有完成数据包排队,
// 函数将等待与完成端口关联的挂起 I/O 操作完成。
//
//
//如果没有完成数据包排队,GetQueueCompletionStatus函数就不会返回,相当于阻塞线程执行
//
// 若要一次取消多个 I/O 完成数据包的排队,请使用 GetQueuedCompletionStatusEx 函数。
//
result = GetQueuedCompletionStatus( Context->Completion, &outSize, &key, &pOvlp, INFINITE );
//
// Obtain the message: note that the message we sent down via FltGetMessage() may NOT be
// the one dequeued off the completion queue: this is solely because there are multiple
// threads per single port handle. Any of the FilterGetMessage() issued messages can be
// completed in random order - and we will just dequeue a random one.
//
//
//
//提取核心I/O数据
message = CONTAINING_RECORD( pOvlp, SCANNER_MESSAGE, Ovlp );
3,调用异步I/O接口
for (j = 0; j < requestCount; j++) {
//
// Allocate the message.
//
#pragma prefast(suppress:__WARNING_MEMORY_LEAK, "msg will not be leaked because it is freed in ScannerWorker")
msg = malloc( sizeof( SCANNER_MESSAGE ) );
if (msg == NULL) {
hr = ERROR_NOT_ENOUGH_MEMORY;
goto main_cleanup;
}
//使用异步(重叠I/O)
memset( &msg->Ovlp, 0, sizeof( OVERLAPPED ) );
//
// Request messages from the filter driver.
//
//异步
//
//FilterGetMessage 使用重叠I/O会立刻返回执行
//
// ScannerWorker 接手处理后续的I/O流程
//从微型筛选器获取消息
hr = FilterGetMessage( port,
&msg->MessageHeader,
FIELD_OFFSET( SCANNER_MESSAGE, Ovlp ),
&msg->Ovlp );
if (hr != HRESULT_FROM_WIN32( ERROR_IO_PENDING )) {
free( msg );
goto main_cleanup;
}
}