iocp

内核对象的概念,是什么?

设备内核对象?

事件内核对象?

IOCP 概念

An I/O completion port is associated with the process that created it and is not sharable between processes. However, a single handle is sharable between threads in the same process.

IOCP 相关的基础 API 只有这三个,相关类型和函数的描述:

1
2
3
4
5
6
7
8
9
HANDLE WINAPI CreateIoCompletionPort(
// An open file handle or INVALID_HANDLE_VALUE.
_In_ HANDLE FileHandle,
// A handle to an existing I/O completion port or NULL.
_In_opt_ HANDLE ExistingCompletionPort,
// Use the CompletionKey parameter to help your application track which I/O operations have completed.
_In_ ULONG_PTR CompletionKey,
_In_ DWORD NumberOfConcurrentThreads
);
1
2
3
4
5
6
7
8
BOOL GetQueuedCompletionStatus(
HANDLE CompletionPort,
LPDWORD lpNumberOfBytesTransferred,
PULONG_PTR lpCompletionKey,
// 指针的指针
LPOVERLAPPED *lpOverlapped,
DWORD dwMilliseconds
);
1
2
3
4
5
6
7
8
BOOL WINAPI PostQueuedCompletionStatus(
_In_ HANDLE CompletionPort,
// 后面三个参数直接转给 GetQueuedCompletionStatus,内部不使用也不做合法校验,可以不做有效赋值
_In_ DWORD dwNumberOfBytesTransferred,
_In_ ULONG_PTR dwCompletionKey,
// In particular, the lpOverlapped parameter need not point to an OVERLAPPED structure.
_In_opt_ LPOVERLAPPED lpOverlapped
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
typedef struct _OVERLAPPED {
// The status code for the I/O request.
ULONG_PTR Internal; //系统内部使用
// The number of bytes transferred for the I/O request.
ULONG_PTR InternalHigh; //系统内部使用
union {
struct {
DWORD Offset;
DWORD OffsetHigh;
} DUMMYSTRUCTNAME;
PVOID Pointer; // 系统内部使用
} DUMMYUNIONNAME;
HANDLE hEvent;
} OVERLAPPED, *LPOVERLAPPED;

typedef struct _WSAOVERLAPPED {
DWORD Internal;
DWORD InternalHigh;
DWORD Offset;
DWORD OffsetHigh;
WSAEVENT hEvent;
} WSAOVERLAPPED, *LPWSAOVERLAPPED;

Any unused members of this structure should always be initialized to zero before the structure is used in a function call.

其余三个属性一般置零 l.Offset = l.OffsetHigh = 0; l.hEvent = NULL;

The WSAOVERLAPPED structure is compatible with the Windows OVERLAPPED structure.

More

1
2
3
4
5
6
7
8
BOOL ReadFile(
HANDLE hFile,
LPVOID lpBuffer,
DWORD nNumberOfBytesToRead,
// 以下两个指针分属同步、异步场景中使用,否则置零
LPDWORD lpNumberOfBytesRead,
LPOVERLAPPED lpOverlapped
);

The WSAStartup function initiates use of the Winsock DLL by a process.

The WSAStartup function must be the first Windows Sockets function called by an application or DLL.

By default, a socket created with the WSASocket function will not have this overlapped attribute set.
In contrast, the socket function creates a socket that supports overlapped I/O operations as the default behavior.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int WSAAPI WSARecv(
SOCKET s,
// A pointer to an array of WSABUF structures.
LPWSABUF lpBuffers,
// The number of WSABUF structures in the lpBuffers array.
DWORD dwBufferCount,
// Use NULL for this parameter if the lpOverlapped parameter is not NULL to avoid potentially erroneous results.
LPDWORD lpNumberOfBytesRecvd,
LPDWORD lpFlags,
// A pointer to a WSAOVERLAPPED structure
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);

int WSAAPI WSASend(
SOCKET s,
LPWSABUF lpBuffers,
DWORD dwBufferCount,
// Use NULL for this parameter if the lpOverlapped parameter is not NULL to avoid potentially erroneous results.
LPDWORD lpNumberOfBytesSent,
DWORD dwFlags,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);

Overlapped IO 重叠输入输出

异步 I/O 技术(Overlapped I/O),避免使用多线程

  1. 激发的文件 handles / 设备内核对象

  2. 激发的 event 对象 / 事件内核对象

    IOEvent 用的是 Overlapped IO 模型。使用起来也比较简单,仅需要将 fd buf overlapped(event) 这4者绑在一起,由内核完成数据的收发,并通过 event 通知应用层,应用层再进行数据操作已经完成后的操作,不需要多余的内存拷贝,数据已经在指定的 buf 上了。C++ SOCKET通信模型(二)IOEvent

  3. 异步过程调用 APCs(Asynchronous Procedure Calls)

  4. I/O completion ports(重要)适用于高负载服务器

IOCP 输入输出完成端口

完成端口(Completion Port)详解

最后,我的建议是,想要使用 基于事件通知的 重叠 I/O 和基于完成例程的 重叠 I/O 的朋友,如果不是特别必要,就不要去使用了,因为这两种方式不仅使用和理解起来也不算简单,而且还有性能上的明显瓶颈