概述
IO完成端口是个比较复杂的内核对象,目前本人也是处于学习中,先写一个文件读写的例子,其中文件读用IO完成端口,文件写暂时用阻塞的方式,避免开始就难理解的局面。
下面直接上代码。
// FileOverlapped.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <Windows.h>
DWORD WINAPI ThreadFunc(LPVOID);
HANDLE hFileRead = INVALID_HANDLE_VALUE;
HANDLE hFileWrite = INVALID_HANDLE_VALUE;
#define LEN_READ_WRITE 1024
DWORD dwFileLen = 0;
DWORD dwFileAlreadyReadLen = 0;
typedef struct
{
OVERLAPPED overlap;
char buf[1024];
} cp_overlapped;
cp_overlapped *pCpOverLapped = NULL;
int main()
{
hFileRead = CreateFile("D:\video\xingjichuanyue.rmvb", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, NULL);
if (hFileRead == INVALID_HANDLE_VALUE)
{
return -1;
}
hFileWrite = CreateFile("D:\video\xingjichuanyue_normal.rmvb", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFileWrite == INVALID_HANDLE_VALUE)
{
return -1;
}
dwFileLen = GetFileSize(hFileRead, NULL);
pCpOverLapped = new cp_overlapped;
pCpOverLapped->overlap.hEvent = NULL;
pCpOverLapped->overlap.Offset = 0;
pCpOverLapped->overlap.OffsetHigh = 0;
HANDLE iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
HANDLE iocp2 = CreateIoCompletionPort(hFileRead, iocp, 10001, 0);
BOOL bRet = ReadFile(hFileRead, pCpOverLapped->buf, LEN_READ_WRITE, NULL, &pCpOverLapped->overlap);
DWORD err = ::GetLastError();
HANDLE hThread;
DWORD threadId;
hThread = CreateThread(NULL, 0, ThreadFunc, (LPVOID)iocp, 0, &threadId); // 创建线程
WaitForSingleObject(hThread, INFINITE);
return 0;
}
DWORD WINAPI ThreadFunc(LPVOID p)
{
HANDLE iocp = (HANDLE)p;
DWORD dwReaded = 0;
DWORD key = 0;
cp_overlapped * s = 0;
while (1)
{
dwReaded = 0;
BOOL bRet = GetQueuedCompletionStatus(iocp, &dwReaded, &key, (LPOVERLAPPED*)&s, INFINITE);
if (bRet)
{
bRet = WriteFile(hFileWrite, s->buf, dwReaded, NULL, NULL);
if (dwReaded <= 0)
{
CloseHandle(hFileWrite);
break;
}
dwFileAlreadyReadLen += dwReaded;
if (dwFileAlreadyReadLen >= dwFileLen)
{
CloseHandle(hFileWrite);
break;
}
pCpOverLapped->overlap.hEvent = NULL;
pCpOverLapped->overlap.Offset += dwReaded;
pCpOverLapped->overlap.OffsetHigh = 0;
bRet = ReadFile(hFileRead, pCpOverLapped->buf, LEN_READ_WRITE, NULL, &pCpOverLapped->overlap);
}
}
return 0;
}
代码里面,线程函数里面有这么两句话,pCpOverLapped->overlap.Offset += dwReaded;
pCpOverLapped->overlap.OffsetHigh = 0; 这个是文件偏移量,告知操作系统,文件从什么位置开始读,这个必须设置,如果不设置,则每次读取的都是最开始的1024个字节。还有就是如果文件读完了,发起ReadFile请求时,GetQueuedCompletionStatus会阻塞,所以判断文件是否读完,需要事先获取文件的大小,这点与同步读不一样,同步读不需要获取文件大小。
最后
以上就是大意爆米花为你收集整理的用IO完成端口实现文件异步读操作的全部内容,希望文章能够帮你解决用IO完成端口实现文件异步读操作所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复