一种高效异步IO机制
-- windows
# 背景描述
在此,简单总结一种高效的异步IO机制,话说也是在windows平台上最为高效的(没有之一)。很久之前就一直有这么一个总结的想法,可惜有时不够自信总觉得总结不到位或存在纰漏,甚至有些错误的理解吧,所以常常就搁下,放弃总结机会了。此时想法不然…即使错误理解了,那也尽快让错误更正了吧。
开始总结吧,即完成通知异步IO机制,简称IOCP。
还有一种同步非堵塞IO机制,重叠IO机制。
# 示例说明
结合Win32-API,以简单的伪代码形式描述该异步IO机制,如下:
struct asyn_io_operation
{
WSAOVERLAPPED overlapped;
...
handle_io_operation(); // do callback function when io-operation completed.
...
};
class more_asyn_io_operation : public asyn_io_operation
{
...
};
init()
{
...
iocp_handle = CreateIoCompletionPort(...);
...
}
uninit()
{
CloseHandle(iocp_handle);
}
post_io_handle()
{
...
iocp_handle = PostQueuedCompletionStatus(iocp_handle,...);
...
}
commit_io_handle()
{
...
asyn_io_operation* io_op_ptr = new more_asyn_io_operation(...);
tcp_sock = socket(...);
udp_sock = socket(...);
...
WSASend(tcp_sock, ... , &io_op_ptr->overlapped, ...); //e.g 1
...
WSARecv(tcp_sock, ... , &io_op_ptr->overlapped, ...); //e.g 2
...
WSASendTo(tcp_sock, ... , &io_op_ptr->overlapped, ...); //e.g 3
...
WSARecvFrom(tcp_sock, ... , &io_op_ptr->overlapped, ...); //e.g 4
...
file_h = CreateFile(...);
...
ReadFile(file_h, ... , &io_op_ptr->overlapped, ...); //e.g 5
...
WriteFile(file_h, ... , &io_op_ptr->overlapped, ...); //e.g 6
...
}
main_thread_do()
{
...
while (true)
{
...
LPWSAOVERLAPPED lpOverlapped;
get_res = GetQueuedCompletionStatus(iocp_handle, ..., lpOverlapped, ...);
asyn_io_operation* io_op_ptr = change_asyn_io_operation(lpOverlapped);
io_op_ptr->handle_io_operation();
...
delete io_op_ptr;
...
if (is_exit)
break;
}
...
}
other_thread_do()
{
...
commit_io_handle();
...
}
{
WSAOVERLAPPED overlapped;
...
handle_io_operation(); // do callback function when io-operation completed.
...
};
class more_asyn_io_operation : public asyn_io_operation
{
...
};
init()
{
...
iocp_handle = CreateIoCompletionPort(...);
...
}
uninit()
{
CloseHandle(iocp_handle);
}
post_io_handle()
{
...
iocp_handle = PostQueuedCompletionStatus(iocp_handle,...);
...
}
commit_io_handle()
{
...
asyn_io_operation* io_op_ptr = new more_asyn_io_operation(...);
tcp_sock = socket(...);
udp_sock = socket(...);
...
WSASend(tcp_sock, ... , &io_op_ptr->overlapped, ...); //e.g 1
...
WSARecv(tcp_sock, ... , &io_op_ptr->overlapped, ...); //e.g 2
...
WSASendTo(tcp_sock, ... , &io_op_ptr->overlapped, ...); //e.g 3
...
WSARecvFrom(tcp_sock, ... , &io_op_ptr->overlapped, ...); //e.g 4
...
file_h = CreateFile(...);
...
ReadFile(file_h, ... , &io_op_ptr->overlapped, ...); //e.g 5
...
WriteFile(file_h, ... , &io_op_ptr->overlapped, ...); //e.g 6
...
}
main_thread_do()
{
...
while (true)
{
...
LPWSAOVERLAPPED lpOverlapped;
get_res = GetQueuedCompletionStatus(iocp_handle, ..., lpOverlapped, ...);
asyn_io_operation* io_op_ptr = change_asyn_io_operation(lpOverlapped);
io_op_ptr->handle_io_operation();
...
delete io_op_ptr;
...
if (is_exit)
break;
}
...
}
other_thread_do()
{
...
commit_io_handle();
...
}
(... 待续 ...)
# 涉及Win32-API
http://msdn.microsoft.com/en-us/library/windows/desktop/ms741394(v=vs.85).aspx
typedef struct _WSAOVERLAPPED {
ULONG_PTR Internal;
ULONG_PTR InternalHigh;
union {
struct {
DWORD Offset;
DWORD OffsetHigh;
};
PVOID Pointer;
};
HANDLE hEvent;
} WSAOVERLAPPED,
*LPWSAOVERLAPPED;
HANDLE WINAPI CreateIoCompletionPort(
__in HANDLE FileHandle,
__in HANDLE ExistingCompletionPort,
__in ULONG_PTR CompletionKey,
__in DWORD NumberOfConcurrentThreads
);
BOOL WINAPI GetQueuedCompletionStatus(
__in HANDLE CompletionPort,
__out LPDWORD lpNumberOfBytes,
__out PULONG_PTR lpCompletionKey,
__out LPOVERLAPPED* lpOverlapped,
__in DWORD dwMilliseconds
);
BOOL WINAPI GetQueuedCompletionStatusEx(
__in HANDLE CompletionPort,
__out LPOVERLAPPED_ENTRY lpCompletionPortEntries,
__in ULONG ulCount,
__out PULONG ulNumEntriesRemoved,
__in DWORD dwMilliseconds,
__in BOOL fAlertable
);
BOOL WINAPI PostQueuedCompletionStatus(
__in HANDLE CompletionPort,
__in DWORD dwNumberOfBytesTransferred,
__in ULONG_PTR dwCompletionKey,
__in LPOVERLAPPED lpOverlapped
);
BOOL WSAAPI WSAGetOverlappedResult(
__in SOCKET s,
__in LPWSAOVERLAPPED lpOverlapped,
__out LPDWORD lpcbTransfer,
__in BOOL fWait,
__out LPDWORD lpdwFlags
);
SOCKET WSAAPI socket(
__in int af,
__in int type,
__in int protocol
);
SOCKET WSASocket(
__in int af,
__in int type,
__in int protocol,
__in LPWSAPROTOCOL_INFO lpProtocolInfo,
__in GROUP g,
__in DWORD dwFlags
);
int WSAIoctl(
__in SOCKET s,
__in DWORD dwIoControlCode,
__in LPVOID lpvInBuffer,
__in DWORD cbInBuffer,
__out LPVOID lpvOutBuffer,
__in DWORD cbOutBuffer,
__out LPDWORD lpcbBytesReturned,
__in LPWSAOVERLAPPED lpOverlapped,
__in LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
int WSASend(
__in SOCKET s,
__in LPWSABUF lpBuffers,
__in DWORD dwBufferCount,
__out LPDWORD lpNumberOfBytesSent,
__in DWORD dwFlags,
__in LPWSAOVERLAPPED lpOverlapped,
__in LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
int WSASend(
__in SOCKET s,
__in LPWSABUF lpBuffers,
__in DWORD dwBufferCount,
__out LPDWORD lpNumberOfBytesSent,
__in DWORD dwFlags,
__in LPWSAOVERLAPPED lpOverlapped,
__in LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
int WSASendTo(
__in SOCKET s,
__in LPWSABUF lpBuffers,
__in DWORD dwBufferCount,
__out LPDWORD lpNumberOfBytesSent,
__in DWORD dwFlags,
__in const struct sockaddr* lpTo,
__in int iToLen,
__in LPWSAOVERLAPPED lpOverlapped,
__in LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
int WSARecvFrom(
__in SOCKET s,
__in_out LPWSABUF lpBuffers,
__in DWORD dwBufferCount,
__out LPDWORD lpNumberOfBytesRecvd,
__in_out LPDWORD lpFlags,
__out struct sockaddr* lpFrom,
__in_out LPINT lpFromlen,
__in LPWSAOVERLAPPED lpOverlapped,
__in LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
BOOL WINAPI ReadFile(
__in HANDLE hFile,
__out LPVOID lpBuffer,
__in DWORD nNumberOfBytesToRead,
__out LPDWORD lpNumberOfBytesRead,
__in LPOVERLAPPED lpOverlapped
);
BOOL WINAPI ReadFileEx(
__in HANDLE hFile,
__out LPVOID lpBuffer,
__in DWORD nNumberOfBytesToRead,
__in LPOVERLAPPED lpOverlapped,
__in LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
HANDLE WINAPI CreateFile(
__in LPCTSTR lpFileName,
__in DWORD dwDesiredAccess,
__in DWORD dwShareMode,
__in LPSECURITY_ATTRIBUTES lpSecurityAttributes,
__in DWORD dwCreationDisposition,
__in DWORD dwFlagsAndAttributes,
__in HANDLE hTemplateFile
);
BOOL WINAPI WriteFileEx(
__in HANDLE hFile,
__in LPCVOID lpBuffer,
__in DWORD nNumberOfBytesToWrite,
__in LPOVERLAPPED lpOverlapped,
__in LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
BOOL WINAPI WriteFile(
__in HANDLE hFile,
__in LPCVOID lpBuffer,
__in DWORD nNumberOfBytesToWrite,
__out LPDWORD lpNumberOfBytesWritten,
__in LPOVERLAPPED lpOverlapped
);
BOOL WINAPI CancelIo(
__in HANDLE hFile
);