Overlapped I/O笔记

要想使用异步的ReadFile或者WriteFile,就要有这个Overlapped I/O。

Overlapped I/O的作用就是当处理大量的读取和写入操作时,不会导致堵塞。因为不用这个Overlapped I/O的话,会导致线程堵塞。

大概需要3步

1、使用CreateFile()创建文件或者打开文件

HANDLE CreateFile(
    LPCTSTR lpFileName, 
    DWORD dwDesiredAccess, 
    DWORD dwShareMode, 
    LPSECURITY_ATTRIBUTES lpSecurityAttributes,
    DWORD dwCreationDispostion , 
    DWORD dwFlagsAndAttributes,//这里设置为FILE_FLAG_OVERLAPPED
    HANDLE hTemplateFile); 

2、使用ReadFile或者WriteFile。

BOOL ReadFile( 
    HANDLE hFile, 
    LPVOID lpBuffer, 
    DWORD nNumberOfBytesToRead, 
    LPDWORD lpNumberOfBytesRead, 
    LPOVERLAPPED lpOverlapped); //传入OVERLAPPED变量

3、使用GetOverlappedResult或者 WaitForSingObject进行等待

 

例子如下:

#include 
#include 

using namespace std;

/*
首先使用 OVERLAPPED  结构, 其中有Event 对象, 可用可不用,这个例子先不用
CreateFile 其中一个参数使用 FILE_FLAG_OVERLAPPED
ReadFile  默认同步, 在最后一个参数使用 OVERLAPPED  ;
ReadFile  返回TRUE ,则代表已经读完了
否则应该检查 GetLastError , 系统是否为此安排了等待.
如果 GetLastError == ERROR_IO_PENDING ,则成功了, 等着取数据, 否则失败
之后可以使用 GetOverlappedResult(最后一个参数为TRUE) / WaitForSingObject 来等待直到完成;
*/


void read_overlapped(const TCHAR * path)
{
	//这里没有使用其中的 Event 对象. 
	OVERLAPPED overlap = { 0 };
	DWORD bytesReaded = 0;
	BOOL ret = FALSE;
	char * buf = new char[8196 * 10];

	// 注意:FILE_FLAG_OVERLAPPED 

	HANDLE hFile = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
	if (INVALID_HANDLE_VALUE == hFile){
		cout << "INVALID_HANDLE_VALUE" << endl;
		return;
	}

	//从哪开始读文件 
	overlap.Offset = 0;

	//注意overlap 需要传入
	ret = ReadFile(hFile, buf, 8196 * 10, &bytesReaded
		, &overlap);

	//直接就完成了, 您的计算机硬盘可真快
	if (ret){
		cout << "done :" << bytesReaded << endl;
		cout << buf << endl;
	}
	else
	{
		//检测一下错误, 确认是否已经进入准备状态
		DWORD err = GetLastError();

		//ok
		if (ERROR_IO_PENDING == err)
		{
			//GetOverlappedResult(hFile,&overlap,&bytesReaded,TRUE); 相当于WaitForSingObject
			cout << "LOADing: " << GetLastError() << endl;
			ret = GetOverlappedResult(hFile, &overlap, &bytesReaded, TRUE);
			if (ret){
				cout << "ret:" << ret << ",bytesread:" << bytesReaded << endl;
			}
			
		}
		else
		{
			cout << "err : " << err << endl;
		}
	}
	CloseHandle(hFile);
}

//多同一个文件多次读取
void read_overlapped2(const TCHAR * path)
{
	HANDLE event_handles[2];
	OVERLAPPED overlap[2] = { 0 };
	char * buf[2] = { 0 };
	DWORD  num = 0;
	HANDLE hFile = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
	if (INVALID_HANDLE_VALUE == hFile){
		cout << "INVALID_HANDLE_VALUE" << endl;
		return;
	}

	BOOL ret = 0;
	int success_len = 0;
	for (int i = 0; i < 2; ++i){
		event_handles[i] = CreateEvent(0, TRUE, FALSE, NULL);
		overlap[i].hEvent = event_handles[i];
		overlap[i].Offset = i * 1000 + i;
		buf[i] = new char[8196 * 1024];
		ret = ReadFile(hFile, buf[i], 8196 + overlap[i].Offset, &num, &overlap[i]);
		if (ret){
			cout << "index:" << i << ", is done" << endl;
			cout << "index:" << i << ",num:" << num;
			cout << "index:" << i << buf[i] << endl;
			++success_len;
		}
		else {
			if (GetLastError() != ERROR_IO_PENDING){
				cout << "index:" << i << "failed" << endl;
				delete[] buf[i];
				SetEvent(event_handles[i]);
			}
			else {
				++success_len;
			}
		}
	}
	cout << "success_len:" << success_len << endl;
	//WaitForMultipleObjects(success_len, event_handles, TRUE, INFINITE);这个要不要无所谓的,因为GetOverlappedResult函数具有等待功能
	ret = GetOverlappedResult(hFile, &overlap[0], &num, FALSE);
	cout << "ret:" << ret << ", num:" << num << endl;
	ret = GetOverlappedResult(hFile, &overlap[1], &num, FALSE);
	cout << "ret:" << ret << ", num:" << num << endl;
	CloseHandle(hFile);

}


int main()
{
	//read_overlapped(L"1.txt");
	read_overlapped2(L"1.txt");
	system("pause");
	return 0;
}

 

你可能感兴趣的:(C++)