GetqueueStatus
#include "stdafx.h"
#include <Windows.h>
#include <process.h>
#include <iostream>
using namespace std;
//完成键
#define CK_READ 1
#define CK_WRITE 2
void ShowErrMsg(LPCSTR lpMsg);
//传给线程函数的参数
typedef struct _tagThreadParam
{
HANDLE hIOCP; //IOCP
LPVOID lpAddr; //读入的内存地址
LARGE_INTEGER liFileSize; //源文件大小
size_t nDataBlockSize; //每次读写的数据块大小
HANDLE hSrc; //源文件
HANDLE hDest; //目的文件
LPOVERLAPPED lpOLPSrc; //源文件的OVERLAPPED结构指针
LPOVERLAPPED lpOLPDest; //目的文件的OVERLAPPED结构指针
}ThreadParam, *LPTHREADPARAM;
int _tmain(int argc, _TCHAR* argv[])
{
/*LPCTSTR lpSrc = TEXT("D:\\SourceSoftware\\myeclipse-8.5.0.rar");
LPCTSTR lpDest = TEXT("D:\\SourceSoftware\\myeclipse-8.5.0_copy.rar");*/
/*LPCTSTR lpSrc = TEXT("D:\\SourceSoftware\\VS2010\\cn_visual_studio_2010_ultimate_x86_dvd_532347.iso");
LPCTSTR lpDest = TEXT("D:\\SourceSoftware\\VS2010\\cn_visual_studio_2010_ultimate_x86_dvd_532347_copy.iso");*/
/*LPCTSTR lpSrc = TEXT("D:\\SourceSoftware\\SQLServer2008\\cn_sql_server_2008_r2_developer_x86_x64_ia64_dvd_522724.iso");
LPCTSTR lpDest = TEXT("D:\\SourceSoftware\\SQLServer2008\\cn_sql_server_2008_r2_developer_x86_x64_ia64_dvd_522724_copy.iso");
*/
/*LPCTSTR lpSrc = TEXT("D:\\SourceSoftware\\SQLServer2008\\cn_sql_server_2008_r2_developer_x86_x64_ia64_dvd_522724.rar");
LPCTSTR lpDest = TEXT("D:\\SourceSoftware\\SQLServer2008\\cn_sql_server_2008_r2_developer_x86_x64_ia64_dvd_522724_copy.rar");*/
LPCTSTR lpSrc = TEXT("D:\\SourceSoftware\\VS2012旗舰版\\VS2012_ULT_chs.iso");
LPCTSTR lpDest = TEXT("D:\\SourceSoftware\\VS2012旗舰版\\VS2012_ULT_chs_copy.iso");
HANDLE hSrcFile = INVALID_HANDLE_VALUE; //源文件句柄
HANDLE hDestFile = INVALID_HANDLE_VALUE; //目标文件句柄
HANDLE hIOCP = NULL; //IOCP
LPVOID lpAddr = NULL; //申请内存地址
__try
{
cout << endl << "开始打开源文件" <<endl;
//源文件
hSrcFile = CreateFile(
lpSrc, //源文件
GENERIC_READ, //读模式
FILE_SHARE_READ, //读共享
NULL, //安全属性
OPEN_EXISTING, //必须存在
FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING,//异步 | 不用缓存
NULL //文件模板为空
);
if(INVALID_HANDLE_VALUE == hSrcFile)
{
ShowErrMsg("源文件打开错误");
return -1;
}
cout << endl << "开始打开目的文件" << endl;
//目的文件
hDestFile = CreateFile(
lpDest, //目的文件
GENERIC_WRITE, //写模式
0, //独占访问
NULL, //安全属性
CREATE_ALWAYS, //总是创建
FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING, //异步 | 不用缓存
hSrcFile //文件属性同源文件
);
if (INVALID_HANDLE_VALUE == hDestFile)
{
ShowErrMsg("目的文件打开错误");
return -2;
}
cout << endl << "开始获取文件尺寸" << endl;
//源文件尺寸
LARGE_INTEGER liFileSize;
BOOL bRet = GetFileSizeEx(hSrcFile, &liFileSize);
if (FALSE == bRet)
{
ShowErrMsg("获取源文件尺寸失败");
return -3;
}
cout << endl << "开始用源文件尺寸设置目的文件大小" << endl;
//设置目的文件指针位置为源文件尺寸 并 设置文件尾
BOOL bRet2 = SetFilePointerEx(hDestFile, liFileSize, NULL, FILE_BEGIN);
BOOL bRet3 = SetEndOfFile(hDestFile);
if (FALSE == bRet2 || FALSE == bRet3)
{
ShowErrMsg("设置目的文件尺寸失败");
return -4;
}
cout << endl << "开始获取磁盘扇区大小 和 系统信息" << endl;
SYSTEM_INFO sysInfo = {0};
GetSystemInfo(&sysInfo);
DWORD dwBytesPerSector = 0UL;
bRet = GetDiskFreeSpace(TEXT("D:"), NULL, &dwBytesPerSector, NULL, NULL);
if (FALSE == bRet)
{
ShowErrMsg("开始获取磁盘扇区大小 错误");
return -5;
}
//读
OVERLAPPED ovlpRead;
ovlpRead.Offset = 0;
ovlpRead.OffsetHigh = 0;
ovlpRead.hEvent = NULL;
//写
OVERLAPPED ovlpWrite;
ovlpWrite.Offset = 0;
ovlpWrite.OffsetHigh = 0;
ovlpWrite.hEvent = NULL;
//创建IOCP 并和 文件关联
hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, sysInfo.dwNumberOfProcessors);
if (NULL == hIOCP)
{
DWORD dwErr = GetLastError();
if (ERROR_ALREADY_EXISTS != dwErr)
{
ShowErrMsg("创建IOCP 失败");
return -6;
}
}
hIOCP = CreateIoCompletionPort(hSrcFile, hIOCP, CK_READ, sysInfo.dwNumberOfProcessors);
hIOCP = CreateIoCompletionPort(hDestFile, hIOCP, CK_WRITE, sysInfo.dwNumberOfProcessors);
//申请扇区大小的5倍的内存
size_t sizeMAX = dwBytesPerSector * 1024 * 64 * 2; //512K * 64 * 2
size_t sizeMIN = dwBytesPerSector * 1024 * 64 * 2;
//申请内存
lpAddr = VirtualAlloc(NULL, sizeMAX, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
if (NULL == lpAddr)
{
ShowErrMsg("申请内存错误");
return -7;
}
//先往IOCP的完成队列插入一个 写完成 项
//写0字节
PostQueuedCompletionStatus(
hIOCP, //IOCP
0, //GetQueuedCompletionStatus取到的传送字节为0
CK_WRITE, //写操作
&ovlpWrite //写OVERLAPPED
);
DWORD dwBytesTrans = 0; //传输字节数
ULONG_PTR ulCompleteKey = 0; //完成键
LPOVERLAPPED lpOverlapped = NULL; //OVERLAPPED结构
BOOL bLastTime = FALSE; //最后一个读操作
int i = 0;
int j = 0;
int nCountZero = 0; //计数
/************************************************************************/
/* 因为前一次只是往IOCP的完成队列插入了一项【写完成】,而并非真的写
只是让下面的代码从 【读操作】开始,
执行序列为: 读-写, 读-写, ... ,读-写
当每个【读操作】完成时:把缓冲区中的数据写入【目的文件】,并更新【源文件】的偏移量
当每个【写操作】完成时:更新【目的文件】的偏移量,
同时,因为操作序列是写操作在后,因此写操作完成后,根据更新后的【源文件】的偏移量
和【源文件】大小做比较,如果大于等于源文件大小,则说明这是最后一次读取操作,则当下一次
写操作完成时 退出循环。 如果当前【源文件偏移量】没有达到【源文件大小】则再次从【源文件】
中读取数据进缓冲区,
/************************************************************************/
while(TRUE)
{
BOOL bRet = GetQueuedCompletionStatus(hIOCP, &dwBytesTrans, &ulCompleteKey, &lpOverlapped, INFINITE);
if (FALSE == bRet)
{
DWORD dwErr = GetLastError();
if (NULL != lpOverlapped)
{
ShowErrMsg("线程函数返回错误, 错误原因:");
cout << dwErr <<endl;
break;
} //if
else
{
if (ERROR_TIMEOUT == dwErr)
{
ShowErrMsg("等待超时");
}
else
{
ShowErrMsg("线程函数返回错误, 错误原因2:");
cout << dwErr <<endl;
}
continue;
} //else
} //if
//读操作完成
if (ulCompleteKey == CK_READ)
{
cout << endl << "-------------第 " << ++ i << " 次操作完成,开始写文件 ---------------- "<<endl;
WriteFile(hDestFile, lpAddr, sizeMIN, NULL, &ovlpWrite);
//读操作完成 更新 源文件的偏移量
LARGE_INTEGER liSrcFile;
liSrcFile.QuadPart = dwBytesTrans;
ovlpRead.Offset += liSrcFile.LowPart;
ovlpRead.OffsetHigh += liSrcFile.HighPart;
} //if
//写操作完成
else if (ulCompleteKey == CK_WRITE)
{
//写操作完成, 更新目的文件的偏移量
LARGE_INTEGER liDestFile;
liDestFile.QuadPart = dwBytesTrans;
ovlpWrite.Offset += liDestFile.LowPart;
ovlpWrite.OffsetHigh += liDestFile.HighPart;
//当前源文件的偏移量
LARGE_INTEGER liTemp;
liTemp.LowPart = ovlpRead.Offset;
liTemp.HighPart = ovlpRead.OffsetHigh;
//当前文件偏移是超过文件大小
if (liTemp.QuadPart >= liFileSize.QuadPart)
{
break;
}
cout << endl << "*************第 " << ++ j << " 次读写操作完成,开始读文件 ***************"<<endl;
ReadFile(hSrcFile, lpAddr, sizeMIN, NULL, &ovlpRead);
} //else if
} //while
SetFilePointerEx(hDestFile, liFileSize, NULL, FILE_BEGIN);
SetEndOfFile(hDestFile);
cout << endl << " $$$$$$$$$$$$$$$$$$$$$ 操作完成 $$$$$$$$$$$$$$$$$" <<endl;
}
__finally
{
cout << endl << "清理资源" <<endl;
if (INVALID_HANDLE_VALUE != hSrcFile)
CloseHandle(hSrcFile);
hSrcFile = INVALID_HANDLE_VALUE;
if(INVALID_HANDLE_VALUE != hDestFile)
CloseHandle(hDestFile);
hDestFile = INVALID_HANDLE_VALUE;
if(NULL != lpAddr)
VirtualFree(lpAddr, 0, MEM_RELEASE | MEM_DECOMMIT);
lpAddr = NULL;
}
cout << endl << endl;
return 0;
}
void ShowErrMsg(LPCSTR lpMsg){ cout << endl << "Some error happened : " << lpMsg << "\n"; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
GetqueueStatus的更多相关文章
- Windows API 函数列表 附帮助手册
所有Windows API函数列表,为了方便查询,也为了大家查找,所以整理一下贡献出来了. 帮助手册:700多个Windows API的函数手册 免费下载 API之网络函数 API之消息函数 API之 ...
- C#封装好的Win32API
Kernel.cs using System; using System.Runtime.InteropServices; using System.Text; using HANDLE = Syst ...
- 英文不好也能快速"记忆" API
英文不好不要紧,把API函数导入打字练习类软件,即是练习打字速度,提高编程效率:也能短时间记忆API. 坚持每天打一遍,约2小时,连续打两周,会对API有很好的记忆,此方法是结合英文学习方法!以下是W ...
- 第12章 纤程(Fiber)
12.1 纤程对象的介绍 (1)纤程与线程的比较 比较 线程(Thread) 纤程(Fiber) 实现方式 是个内核对象 在用户模式中实现的一种轻量级的线程,是比线程更小的调度单位. 调度方式 由Mi ...
- Windows 消息机制详解
总的来说: MSG包括: 窗口句柄,指示MSG发送的目的窗口 消息标识 lPARAM.wParam 发送时间 发送时的鼠标位置 关于消息队列: Windows系统有一个系统消息队列 每个线程都有一 ...
- WaitForMultipleObject与MsgWaitForMultipleObjects用法
http://blog.csdn.net/byxdaz/article/details/5638680 用户模式的线程同步机制效率高,如果需要考虑线程同步问题,应该首先考虑用户模式的线程同步方法. 但 ...
- Chrome中的消息循环
主要是自己做个学习笔记吧,我经验也不是很丰富,以前学习多线程的时候就感觉写多线程程序很麻烦.主要是线程之间要通信,要切线程,要同步,各种麻烦.我本身的工作经历决定了也没有太多的工作经验,所以chrom ...
- DELPHI下API简述(1800个API)
DELPHI下API简述 http://zero.cnbct.org/show.asp?id=144 auxGetDevCaps API 获取附属设备容量 auxGetNumDevs API 返回附属 ...
- API函数
1. API之网络函数 WNetAddConnection 创建同一个网络资源的永久性连接 WNetAddConnection2 创建同一个网络资源的连接 WNetAddConnection3 创建同 ...
随机推荐
- Content Provider基础
1.Content Provider为存储和获取数据提供了统一的接口. 2.Content Provider可以在不同的应用程序之间共享数据. 3.Android为常见的一些数据提供了ContentP ...
- PHP 获取header 的自定义参数值
$.ajax({ type: "GET", url: "default.aspx", beforeSend: function(request) { reque ...
- Linux 命令 - mknod
mknod 创建块设备或者字符设备文件.此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.SUSE.openSUSE.Fedora. 1.语法 mknod [选项] 设备名 设备类 ...
- SQL注入的原理及分析
注入攻击的本质:将用户输入的数据当做代码执行. 有2个限制条件: 1.用户能够控制输入. 2.原本程序要执行的代码,拼接了用户输入的数据后进行执行. 定义:用户输入的数据被当做SQL语句执行. 以下面 ...
- Centos7下 Oracle11G自动备份
1.创建备份目录: [root@Centos ~]# mkdir -p /home/oracle/backup 2.设置目录权限: [root@Centos ~]# chown -R oracle:o ...
- Timetable CodeForces - 946D (预处理+背包)
题意:n天m节课,最多可以逃k节课,每天在学校待的时间为该天上的第一节课到最后一节课持续的时间.问怎样逃课可以使这n天在学校待的时间最短,输出最短的时间. 分析: 1.预处理出每天逃j节课时在学校待的 ...
- 基于LAMP实现后台活动发布和前端扫码签到系统
目的 无论是公司.学校和社会团体,都会举办各式各样的活动,比如运动会.部门会议.项目会议.野炊.团建等.作为团队管理者来讲,当然希望能够把这类活动转移到线上形成完整的系统,类似于电子流的形式.本文以学 ...
- IO、阻塞和非阻塞、目录
系统函数.系统调用 系统函数 open/close函数 函数原型 man 2 open // open, creat - open and possibly create a file or devi ...
- 010、MySQL日期时间戳转化为文本日期时间
#时间戳转化文本时间 SELECT from_unixtime( unix_timestamp( curdate( ) ) ); #时间戳转化文本时间格式化 SELECT from_unixtime( ...
- Java 的 String.split 函数,消除空字符串
代码: String str = "the music made it hard to concentrate"; String delims = "[ ]+" ...