1、关于IOCP
IOCP即IO完成端口,是一种高伸缩高效率的异步IO方式,一个设备或文件与一个IO完成端口相关联,当文件或设备的异步IO操作完成的时候,去IO完成端口的【完成队列】取一项,根据完成键(Complete Key)来判断是哪个设备或文件的操作完成,然后再根据实际情况进行处理。
2、相关API 和 数据结构
将一个已完成的IO通知追加到IOCP的【完成队列】中
BOOL PostQueuedCompletionStatus(
HANDLE hCompletionPort, //IO完成端口
DWORD dwNumBytes, //传输的字节数
ULONG_PTR completionKey, //完成键
OVERLAPPED* pOverlapped //设备或文件发送异步IO请求时的关联OVERLAPPED结构指针
)
从【完成队列】中取一项
BOOL GetWQueuedCompletionStatus(
HANDLE hCompletionPort, //IOCP
PWORD pdwNumberOfBytesTransferred, //已传输字节数
PULONG_PTR pCompletionKey, //完成键
OVERLAPPED** ppOverlapped, //与文件或设备关联的OVERLAPPED结构,指针的指针,[out]
DWORD dwMilliseconds //等待时间
)
创建IOCP 或 将一个文件/设备与一个IOCP关联起来
HANDLE WINAPI CreateIoCompletionPort(
__in HANDLE FileHandle, //文件 设备句柄
__in_opt HANDLE ExistingCompletionPort, //一个IOCP句柄
__in ULONG_PTR CompletionKey, //完成键
__in DWORD NumberOfConcurrentThreads //允许运行的最大线程数量
);
新建
HANDLE hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 一个数量);
关联
CreateIoCompletionPort(hFile, hIOCP, CK_XXX, 一个数量);
OVERLAPPED结构
typedef struct _OVERLAPPED {
ULONG_PTR Internal; //错误代码,系统管理
ULONG_PTR InternalHigh; //传输自字节数 系统管理
union {
struct {
DWORD Offset; //起始偏移 地位, 需要特别注意:大文件时这个值容易溢出
DWORD OffsetHigh; //起始偏移 高位
} ;
PVOID Pointer;
} ;
HANDLE hEvent; //事件内核对象
} OVERLAPPED, *LPOVERLAPPED;
IOCP的五个数据结构
①设备列表
表示与该端口相关联的一个或多个设备
②IO完成队列 FIFO
包含已传输字节数、完成键、OVERLAPPED结构、错误代码等
当IO请求完成 或 调用PostQueuedCompletionStatus时 会往该队列中添加项
③等待线程队列 FILO
当线程池中每个线程调用GetQueuedCompletionStatus时,调用线程的线程标示符会被添加到这个等待线程队列,这使得IOCP始终都能够知道有哪些线程正在等待对已完成的IO请求进行处理。
④已释放线程列表
对IO请求后进行处理的线程由于某种原因被挂起后,又被唤醒,就进入以释放线程列表
⑤已暂停线程列表
对IO请求后进行处理的线程由于某种原因被挂起后进入已暂停线程列表
3、说明
IOCP中运行运行的最大线程数一般是CPU个数
线程池中的最大线程数一般是CPU个数的2倍
下一篇用一个复制文件的例子来演示一下IOCP的使用