非同步IO、APC、IO完成埠、執行緒池與高效能伺服器之三 IO完成埠
IO完成埠下面摘抄於MSDN《I/O Completion Ports》,smallfool翻譯,原文請參考CSDN文件中心文章《I/O Completion Ports》,。
I/O 完成埠是一種機制,通過這個機制,應用程式在啟動時會首先建立一個執行緒池,然後該應用程式使用執行緒池處理非同步I/O請求。這些執行緒被建立的唯一目的就是 用於處理I/O請求。對於處理大量併發非同步I/O請求的應用程式來說,相比於在I/O請求發生時建立執行緒來說,使用完成埠(s)它就可以做的更快且更有
效率。
CreateIoCompletionPort函式會使一個I/O完成埠與一個或多個檔案控制代碼發生關聯。當與一個完成埠相關的檔案控制代碼上啟動的非同步I/O
PostQueuedCompletionStatus函式允許應用程式可以針對自定義的專用I/O完成包進行排隊,而無需啟動一個非同步I/O操作。這點對於通知外部事件的工作者執行緒來說很有用。在沒有更多的引用針對某個完成埠時,需要釋放該完成埠。該完成埠控制代碼以及與該完成埠相關聯的所有檔案控制代碼都需要被釋放。呼叫CloseHandle可以釋放完成埠的控制代碼。下面的程式碼利用IO完成埠做了一個簡單的執行緒池。
/************************************************************************/
/* Test IOCompletePort. */
/************************************************************************/
static HANDLE CompleteEvent = NULL;
DWORD UserProc1(LPVOID UserParam)
{
printf("enter User Proc. /n");
SetEvent(CompleteEvent);
return 0;
}
typedef DWORD (*WORK_ITEM_PROC)(LPVOID) ;
DWORD WINAPI IOCPWorkThread(PVOID pParam)
{
HANDLE CompletePort = (HANDLE)pParam;
PVOID UserParam;
WORK_ITEM_PROC UserProc;
LPOVERLAPPED pOverlapped;
for(;;)
{
BOOL bRet = GetQueuedCompletionStatus(
CompletePort,
(LPDWORD)&UserParam,
(LPDWORD)&UserProc,
&pOverlapped,
INFINITE);
//ASSERT(bRet);
if(UserProc == NULL) // Quit signal.
break;
// execute user's proc.
UserProc(UserParam);
}
return 0;
}
void TestIOCompletePort(BOOL bWaitMode, LONG ThreadNum)
{
HANDLE CompletePort;
OVERLAPPED Overlapped = { 0, 0, 0, 0, NULL };
CompletePort = CreateIoCompletionPort(
INVALID_HANDLE_VALUE,
NULL,
NULL,
0);
// Create threads.
for(int i=0; i<ThreadNum; i++)
{
HANDLE hThread = CreateThread(NULL,
0,
IOCPWorkThread,
CompletePort,
0,
NULL);
CloseHandle(hThread);
}
CompleteEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
for(int i=0; i<20; i++)
{
PostQueuedCompletionStatus(
CompletePort,
(DWORD)bWaitMode,
(DWORD)UserProc1,
&Overlapped);
}
WaitForSingleObject(CompleteEvent, INFINITE);
CloseHandle(CompleteEvent);
// Destroy all threads.
for(int i=0; i<ThreadNum; i++)
{
PostQueuedCompletionStatus(
CompletePort,
NULL,
NULL,
&Overlapped);
}
Sleep(10); // wait all thread exit.
CloseHandle(CompletePort);
}