IO Completion Port与文件IO

尽管现在网络上关于IO Completion Port的文章多如牛毛,但绝大多数是以socket为例的。而socket I/O比File I/O要复杂得多,导致相应的例子也比较复杂。下面是一个使用IO Completion Port实现File I/O的程序。为了简单,没有错误处理。

 1 #include <iostream>
 2 #include <string.h>
 3 #include "windows.h"
 4 
 5 using namespace std;
 6 
 7 // 文件操作次数
 8 #define NR_FILE_OP_TIMES    4
 9 // 每次IO的数据量
10 #define BUFFER_SIZE         (1024 * 1024)
11 
12 static DWORD WINAPI ThreadFunc(LPVOID param);
13 
14 int main()
15 {
16     HANDLE hFile = CreateFile("test.dat",
17                               GENERIC_READ | GENERIC_WRITE,
18                               FILE_SHARE_READ,
19                               0,
20                               CREATE_ALWAYS,
21                               FILE_FLAG_OVERLAPPED,
22                               0);
23 
24     // 初始化数据缓冲区
25     char* ppBuf[NR_FILE_OP_TIMES];
26     for(int i = 0; i < NR_FILE_OP_TIMES; i++)
27     {
28         ppBuf[i] = new char[BUFFER_SIZE];
29         memset(ppBuf[i], i, BUFFER_SIZE);
30     }
31 
32     // 初始化overlapped结构
33     OVERLAPPED overlapped[NR_FILE_OP_TIMES];
34     memset(overlapped, 0, sizeof(OVERLAPPED) * NR_FILE_OP_TIMES);
35 
36     // 创建completion port
37     HANDLE hPort = CreateIoCompletionPort(hFile, 0, 0, 0);
38 
39     // 创建Threads
40     HANDLE hThread[NR_FILE_OP_TIMES];
41     for(int i = 0; i < NR_FILE_OP_TIMES; i++)
42     {
43         // Create Thread Pool
44         hThread[i] = CreateThread(0, 0, ThreadFunc, &hPort, 0, 0);
45     }
46 
47     // 启动File I/O
48     DWORD bytesWritten;
49     HANDLE hEvent[NR_FILE_OP_TIMES];
50     for(int i = 0; i < NR_FILE_OP_TIMES; i++)
51     {
52         overlapped[i].Offset = BUFFER_SIZE * i;
53         hEvent[i] = CreateEvent(0, TRUE, FALSE, 0);
54         overlapped[i].hEvent = hEvent[i];
55         WriteFile(hFile, ppBuf[i], BUFFER_SIZE, &bytesWritten, &(overlapped[i]));
56     }
57 
58     // 等待I/O完成
59     WaitForMultipleObjects(4, hEvent, TRUE, INFINITE);
60 
61     // Cleanup
62     for(int i = 0; i < NR_FILE_OP_TIMES; i++)
63     {
64         delete ppBuf[i];
65         CloseHandle(hThread[i]);
66     }
67     CloseHandle(hPort);
68     CloseHandle(hFile);
69     return 0;
70 }
71 
72 static DWORD WINAPI ThreadFunc(LPVOID param)
73 {
74     HANDLE hPort = *((HANDLE *)param);
75 
76     OVERLAPPED* pOverlapped;
77     DWORD bytesTransferred;
78     DWORD key;
79 
80     GetQueuedCompletionStatus(hPort,
81                               &bytesTransferred,
82                               &key,
83                               &pOverlapped,
84                               INFINITE);
85 
86     // 打印出I/O相关信息,设置Event,然后这个Thread就退出了。
87     cout << "Bytes transferred from " << pOverlapped->Offset << ", length " << bytesTransferred << endl;
88 
89     SetEvent(pOverlapped->hEvent);
90 
91     return 0;
92 }

下面是运行结果:

从运行结果看,写入顺序是1 2 3 4,完成顺序是1 2 4 3。

原文地址:https://www.cnblogs.com/byeyear/p/2711088.html