2012年3月30日星期五

一种高效异步IO机制



一种高效异步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();
     ...
}

(... 待续 ...)



# 涉及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
);

没有评论:

发表评论