Poedu_Windows_IOCP初窥

IOCP

IOCP是唯一一个不需要安全属性的Windows内核对象。 这是因为IO完成端口在设计时就是只在一个进程中使用。

原理

通常的办法是,线程池中的工作线程的数量与CPU内核数量相同,以此来最小化线程切换代价。一个IOCP对象,在操作系统中可关联着多个Socket和(或)文件控制端。 IOCP对象内部有一个先进先出(FIFO)队列,用于存放IOCP所关联的输入输出端的服务请求完成消息。请求输入输出服务的进程不接收IO服务完成通知,而是检查IOCP的消息队列以确定IO请求的状态。 (线程池中的)多个线程负责从IOCP消息队列中取走完成通知并执行数据处理;如果队列中没有消息,那么线程阻塞挂起在该队列。这些现成从而实现了负载均衡。

引自维基百科

IOCP是Windows提供给我们的一整套的东西(工具库)

1.创建一个队列(一个完成端口会创建一个)

包含了设备

可以有多个设备对应一个完成端口

2.设备操作的队列

对我设备进行挨个的操作

3.线程池

多个线程

创建一个完成端口

使用CreateIoCompletionPort

原型
HANDLE WINAPI CreateIoCompletionPort(
_In_ HANDLE FileHandle, // 设备内核对象
_In_opt_ HANDLE ExistingCompletionPort, // 已存在的完成端口
_In_ ULONG_PTR CompletionKey, // 完成端口的一个Key值,我们可以通过define进行一个设置
_In_ DWORD NumberOfConcurrentThreads // 创建多少个线程,默认值为0, 表示一个核心对应一个线程, 也就是说, 8核心就是8线程, 4核心就是4线程,不建议设置为100个这样的数量,线程切换会消耗资源
);

如果是8核,实际的物理线程就是8个,可以设置为100个线程,但是它只是做了一个线程模拟,因为它真正只能做到8个线程

两种创建方式:

1.先创建一个端口,再打开文件,再进行端口与设备的绑定

//创建一个端口
HANDLE hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
//打开一个文件
HANDLE hFile = CreateFile(TEXT("Demo.txt"),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
FILE_FLAG_OVERLAPPED,
NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
// 绑定设备和端口
CreateIoCompletionPort(hFile,
hIOCP, //指定端口
IOCP_KEY_READ,
0);
OVERLAPPED oRead = {0};
oRead.Offset = 0;
DWORD dwNumberOfBytesTransferred = 100;
}
else
{
// GetLastError()
}

2.创建一个与指定文件绑定的端口

HANDLE hIOCP = CreateIoCompletionPort( hFile,
NULL,
IOCP_KEY_READ,
0);

同样也是要拿到文件句柄,只是少了一个创建自由端口的步骤,直接与文件进行绑定了而已

插入一个请求

PostQueuedCompletionStatus

原型

BOOL WINAPI PostQueuedCompletionStatus(
_In_ HANDLE CompletionPort, // 完成端口
_In_ DWORD dwNumberOfBytesTransferred, // 传输的数据长度, 用于GetQueuedCompletionStatus获取的时候
_In_ ULONG_PTR dwCompletionKey, // IO完成端口的KEY
_In_opt_ LPOVERLAPPED lpOverlapped // OVERLAPPED结构体指针
);

从指定的IO完成端口取数据

GetQueuedCompletionStatus

原型:

BOOL WINAPI GetQueuedCompletionStatus(
_In_ HANDLE CompletionPort, // IO完成端口
_Out_ LPDWORD lpNumberOfBytes, // 取出的数据数的指针
_Out_ PULONG_PTR lpCompletionKey, // IO完成端口的KEY
_Out_ LPOVERLAPPED *lpOverlapped, // 指向OVERLAPPED结构体指针的指针
_In_ DWORD dwMilliseconds // 等待的毫秒数
);

注意:

如果没有完成数据包队列, 该功能将等待与完成端口关联的待处理的IO操作完成.

如果在指定时间内没有出现完成数据包, 则函数超时, 返回FALSE, 并将 *lpOverlapped 设置为NULL

如果dwMilliseconds是INFINITE, 则该函数永远不会超时

如果dwMilliseconds为零, 并且没有IO操作出现, 则该函数将立即超时.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值