异步设备IO 《windows核心编程》第10章学习
异步IO操作与同步操作区别:
- 在CreateFile里的FILE_FLAG_OVERLAPPED标志
- 异步操作函数LPOVERLAPPED参数
接收IO请求完成通知
- 触发设备内核对象 
 缺点:同一个设备内核对象有可能进行多次读写操作,这样第一个完成这个设备内核对象就会被触发,所以这种方式不可以使用于这种情形void Test1() 
 {
 HANDLE hFile = ::CreateFile(_T("aaa.txt"),
 GENERIC_READ,
 FILE_SHARE_READ,
 NULL,
 OPEN_EXISTING,
 FILE_FLAG_OVERLAPPED,
 NULL);
 if(!hFile)
 {
 wcout<<L"CreateFile Failed ErroCode:"<<::GetLastError()<<endl;
 return ;
 }
 DWORD dwFileSize = ::GetFileSize(hFile,);
 wcout<<L"FileSize:"<<dwFileSize<<endl;
 char * pFileContent = new char[];
 DWORD dwReaded = ;
 OVERLAPPED o_Read = {};
 DWORD bReadDone = ::ReadFile(hFile,
 pFileContent,
 ,
 &dwReaded,
 &o_Read);
 DWORD dwError = ::GetLastError();
 if(!bReadDone && (dwError == ERROR_IO_PENDING))
 {
 WaitForSingleObject(hFile,INFINITE);
 bReadDone = TRUE;
 } if(bReadDone)
 wcout<<L"I/O Code:"<<o_Read.Internal<<" TransedBytes:"<<o_Read.InternalHigh<<endl;
 else
 wcout<<"Error:"<<::GetLastError()<<endl;
 ::CloseHandle(hFile);
 delete [] pFileContent;
 }
- 触发事件内核对象 
void Test2() 
 {
 HANDLE hFile = ::CreateFile(_T("aaa.txt"),
 GENERIC_WRITE,
 FILE_SHARE_READ,
 NULL,
 OPEN_EXISTING,
 FILE_FLAG_OVERLAPPED,
 NULL);
 if(!hFile)
 {
 wcout<<L"CreateFile Failed ErroCode:"<<::GetLastError()<<endl;
 return ;
 }
 DWORD dwFileSize = ::GetFileSize(hFile,);
 wcout<<L"FileSize:"<<dwFileSize<<endl;
 LARGE_INTEGER liDis = {};
 LARGE_INTEGER liRet = {};
 ::SetFilePointerEx(hFile,liDis,&liRet,FILE_END);
 wcout<<L"PreWrite File Pos:"<<liRet.LowPart<<endl;
 char * pFileContent = new char[];
 memset(pFileContent,'z',);
 DWORD dwReaded = ;
 OVERLAPPED o_Write = {};
 o_Write.Offset = liRet.LowPart;
 o_Write.hEvent = ::CreateEvent(NULL,FALSE,FALSE,NULL);
 DWORD bReadDone = ::WriteFile(hFile,
 pFileContent,
 ,
 &dwReaded,
 &o_Write);
 DWORD dwError = ::GetLastError();
 if(!bReadDone && (dwError == ERROR_IO_PENDING))
 {
 WaitForSingleObject(o_Write.hEvent,INFINITE);
 bReadDone = TRUE;
 } if(bReadDone)
 wcout<<L"I/O Code:"<<o_Write.Internal<<" TransedBytes:"<<o_Write.InternalHigh<<endl;
 else
 wcout<<"Error:"<<::GetLastError()<<endl;
 ::CloseHandle(hFile);
 delete [] pFileContent;
 }
- 可提醒IO 
void Test3() 
 {
 //可提醒IO
 HANDLE hFile = ::CreateFile(_T("aaa.txt"),
 GENERIC_WRITE,
 FILE_SHARE_READ,
 NULL,
 OPEN_EXISTING,
 FILE_FLAG_OVERLAPPED,
 NULL);
 if(!hFile)
 {
 wcout<<L"CreateFile Failed ErroCode:"<<::GetLastError()<<endl;
 return ;
 }
 DWORD dwFileSize = ::GetFileSize(hFile,);
 wcout<<L"FileSize:"<<dwFileSize<<endl;
 LARGE_INTEGER liDis = {};
 LARGE_INTEGER liRet = {};
 ::SetFilePointerEx(hFile,liDis,&liRet,FILE_END);
 wcout<<L"PreWrite File Pos:"<<liRet.LowPart<<endl;
 char * pFileContent = new char[];
 memset(pFileContent,'g',);
 DWORD dwReaded = ;
 OVERLAPPED o_Write = {};
 o_Write.Offset = liRet.LowPart;
 DWORD bReadDone = ::WriteFileEx(hFile,
 pFileContent,
 ,
 &o_Write,
 FileIOCompletionRoutine); ::CloseHandle(hFile);
 SleepEx(,TRUE);
 delete [] pFileContent;
 }可提醒IO的优劣: (1)由于回调函数的原因,最终不得不把大量信息放在全局变量中。使代码变的更加复杂 (2)发出请求线程和完成处理必须是同一线程,没有达到线程负载均衡 可提醒IO相关函数 (1)QueueUserAPC函数 a.这个函数允许我们手动增加APC项。 b.可以强制线程退出等待状态比如WaitForSingleObjectEx 以下是示例代码 VOID WINAPI APCFunc(ULONG_PTR pvParam) 
 {
 //Nothing To Do
 } UINT WINAPI ThreadFunc(PVOID pvParam)
 {
 wcout<<L"start Wait...."<<endl;
 DWORD dw = ::WaitForSingleObjectEx(pvParam,INFINITE,TRUE);
 if(dw == WAIT_OBJECT_0)
 {
 wcout<<L"Event signaled"<<endl;
 return ;
 }
 else if(dw == WAIT_IO_COMPLETION)
 {
 wcout<<L"QueueUserApc Forced us out of a wait state"<<endl;
 return ;
 }
 return ;
 }
 void Test4()
 {
 //利用QueueUserApc来停止线程等待
 HANDLE hEvent = ::CreateEvent(NULL,FALSE,FALSE,NULL);
 HANDLE hThread = (HANDLE) _beginthreadex(NULL,,ThreadFunc,hEvent,,NULL);
 Sleep();
 QueueUserAPC(APCFunc,hThread,NULL);
 WaitForSingleObject(hThread,INFINITE);
 CloseHandle(hThread);
 CloseHandle(hEvent);
 }
- I/O完成端口 
 待续void Test5() 
 {
 //I/O完成端口
 TCHAR SrcFileName[MAXSIZE];
 TCHAR DesFileName[MAXSIZE]; cout<<"请输入源文件名:\n";
 wcin>>SrcFileName; cout<<"请输入目的文件名:\n";
 wcin>>DesFileName; HANDLE hSrcFile=CreateFile(SrcFileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_ALWAYS,FILE_FLAG_OVERLAPPED,NULL);
 if(hSrcFile==INVALID_HANDLE_VALUE)
 {
 printf("文件打开失败!");
 }
 DWORD FileSizeHigh;
 DWORD FileSize=GetFileSize(hSrcFile,&FileSizeHigh); HANDLE hDstFile=CreateFile(DesFileName,GENERIC_WRITE,,NULL,CREATE_NEW,FILE_FLAG_OVERLAPPED,NULL); //创建完成端口
 HANDLE hIOCP=CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,,);
 if(hIOCP==NULL)
 {
 printf("完成端口创建失败!");
 } //绑定完成端口
 CreateIoCompletionPort(hSrcFile,hIOCP,READ_KEY,);
 CreateIoCompletionPort(hDstFile,hIOCP,WRITE_KEY,); OVERLAPPED ov={};
 PostQueuedCompletionStatus(hIOCP,,WRITE_KEY,&ov);
 OVERLAPPED ovSrc={};
 OVERLAPPED ovDes={};
 ULONG_PTR CompletionKey;
 BYTE* pBuffer=new BYTE[BUFFERSIZE];
 int i=;
 int j=;
 while(true)
 {
 DWORD nTransfer;
 OVERLAPPED* o; GetQueuedCompletionStatus(hIOCP,&nTransfer,&CompletionKey,&o,INFINITE);
 switch(CompletionKey)
 {
 case READ_KEY:
 //代表读取IO操作已经完成,进行下一步写入操作
 WriteFile(hDstFile,pBuffer,o->InternalHigh,NULL,&ovDes);
 cout<<"write:"<<++i<<endl;
 ovDes.Offset+=o->InternalHigh;
 //if(ovDes.Offset== FileSize/1024 )
 // return 0;
 break;
 case WRITE_KEY:
 //代表写入IO操作已经完成,进行下一步读取操作
 memset(pBuffer,,BUFFERSIZE*sizeof(BYTE));
 if(ovSrc.Offset < FileSize)//文件读取未完成
 {
 DWORD nBytes;
 if(ovSrc.Offset+BUFFERSIZE < FileSize)
 nBytes=BUFFERSIZE;
 else
 nBytes=FileSize-ovSrc.Offset;
 ReadFile(hSrcFile,pBuffer,nBytes,NULL,&ovSrc);
 cout<<"read:"<<++j<<endl; ovSrc.Offset+=nBytes;
 }
 else
 return ;
 break;
 default:
 break; }
 } return ;
 }
异步设备IO 《windows核心编程》第10章学习的更多相关文章
- windows核心编程 第8章201页旋转锁的代码在新版Visual Studio运行问题
		// 全局变量,用于指示共享的资源是否在使用 BOOL g_fResourceInUse = FALSE; void Func1() { //等待访问资源 while(InterlockedExcha ... 
- windows核心编程 第5章job lab示例程序 解决小技巧
		看到windows核心编程 第5章的最后一节,发现job lab例子程序不能在我的系统(win8下)正常运行,总是提示“进程在一个作业里” 用process explorer程序查看 ... 
- Windows核心编程 第十一章 线程池的使用
		第11章 线程池的使用 第8章讲述了如何使用让线程保持用户方式的机制来实现线程同步的方法.用户方式的同步机制的出色之处在于它的同步速度很快.如果关心线程的运行速度,那么应该了解一下用户方式的同步机制是 ... 
- Windows核心编程 第七章 线程的调度、优先级和亲缘性(下)
		7.6 运用结构环境 现在应该懂得环境结构在线程调度中所起的重要作用了.环境结构使得系统能够记住线程的状态,这样,当下次线程拥有可以运行的C P U时,它就能够找到它上次中断运行的地方. 知道这样低层 ... 
- windows核心编程---第六章 线程的调度
		每个线程都有一个CONTEXT结构,保存在线程内核对象中.大约每隔20ms windows就会查看所有当前存在的线程内核对象.并在可调度的线程内核对象中选择一个,将其保存在CONTEXT结构的值载入c ... 
- 《windows核心编程》 17章 内存映射文件
		内存映射文件主要用于以下三种情况: 系统使用内存映射文件载入并运行exe和dll,这大量节省了页交换文件的空间以及应用程序的启动时间 开发人员可以使用内存映射文件来访问磁盘上的数据文件.这使得我们可以 ... 
- Windows核心编程 第十七章 -内存映射文件(下)
		17.3 使用内存映射文件 若要使用内存映射文件,必须执行下列操作步骤: 1) 创建或打开一个文件内核对象,该对象用于标识磁盘上你想用作内存映射文件的文件. 2) 创建一个文件映射内核对象,告诉系统该 ... 
- Windows核心编程 第六章 线程基础知识 (上)
		第6章 线程的基础知识 理解线程是非常关键的,因为每个进程至少需要一个线程.本章将更加详细地介绍线程的知识.尤其是要讲述进程与线程之间存在多大的差别,它们各自具有什么作用.还要介绍系统如何使用线程内核 ... 
- windows核心编程---第七章 用户模式下的线程同步
		用户模式下的线程同步 系统中的线程必须访问系统资源,如堆.串口.文件.窗口以及其他资源.如果一个线程独占了对某个资源的访问,其他线程就无法完成工作.我们也必须限制线程在任何时刻都能访问任何资源.比如在 ... 
- 《Windows核心编程》第九章——用内核对象进行线程同步
		先举一个有bug的例子: #include <iostream> #include <windows.h> #include <process.h> using n ... 
随机推荐
- PAT乙级  1013. 数素数 (20)
			1013. 数素数 (20) 时间限制 100 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 令Pi表示第i个素数.现任给两个正整 ... 
- 三层与MVC
			三层架构(3-tier architecture) 我们平时总是将三层架构与MVC混为一谈,殊不知它俩并不是一个概念.下面我来为大家揭晓我所知道的一些真相. 首先,它俩根本不是一个概念. 三层架构是一 ... 
- Angularjs之基本概念梳理(一)
			1.Angularjs指令属性ng-app和ng-controller的理解 ng-app指令-标记了AngularJS脚本的作用域,在<html>中添加ng-app属性即说明整个< ... 
- Intel Edison 参考链接2
			Edison的breakout板子的引脚: http://iotdk.intel.com/docs/master/mraa/java/edison.html Edison的引脚 http://www. ... 
- Perl 和 Python 的比较 【转】
			转自:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&id=4662991&uid=608135 作为万年Perl 党表示最近开 ... 
- Linux驱动开发 -- 打开dev_dbg() 【转】
			转自:http://blog.chinaunix.net/uid-20672559-id-3383042.html linux设备驱动调试,我们在内核中看到内核使用dev_dbg来控制输出信息,这个函 ... 
- 有关对字符串的处理,需要用到List时的简化写法
			这是项目中的需要根据ComputerName来获取IP的一个方法,如果出现多个ComputerName,需要将多个ComputerName的字符串以“:”分开,传进方法中,然后再处理不同的Name,然 ... 
- Linux C socket 编程之TCP
			推荐:http://www.cnblogs.com/tianshuai11/archive/2011/11/30/2477224.html 
- java 数组基本操作(一维)
			1.数组的声明: 数组类型 数组名[] 2.数组的表示方法 想使用数组中的值,可以使用索引来实现,数组是从0开始的,使用时格式为:数组名[i],比如 a[1],代表第二个值 在数组中要使用数组的长度 ... 
- 八大排序算法之二希尔排序(Shell Sort)
			希尔排序是1959 年由D.L.Shell 提出来的,相对直接排序有较大的改进.希尔排序又叫缩小增量排序 基本思想: 先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录 ... 
