10.3 执行同步设备I/O

(1)对设备读写操作的函数

  ①ReadFile/WriteFile函数

参数

描述

hFile

文件句柄

pvBuffer

指向要接收文件数据的缓冲区或把缓冲区数据写入设备

nNumbytesToRead

要读取的字节数或写入的字节数

pdwNumBytes

实际读取的字节数或写入的字节数

pOverlapped

指向OVERLAPPED结构体。

①要进行同步读写时,该参数为NULL,同时打开设备的时候,标志不能指定为FILE_FLAG_OVERLAPPED。

②要进行异步读写时,须指定该参数,同时打开设备时设置FILE_FLAG_OVERLAPPED标志。此时,函数不再等待,会直接返回FALSE,通过用GetLastError将得到ERROR_IO_PENDING

返回值

成功——非0。如果dwNumBytes=0,表示文件指针超过文件未尾。

失败——FALSE。如果是异步调用,也返回FALSE,可通过GetLastError获得更详细的信息。

【说明】

  ①要进行同步和异步的设置与最后一个参数pOverlapped的密切相关

  ②ReadFile只能用于哪些用GENERIC_READ打开的设备,同理WriteFile只能用于那些用GENERIC_WRITE标志打开的设备

(2)将数据刷新到设备

  ①在CreateFile函数时可通过传FILE_FLAG_NO_BUFFERING等标志来决定是否对数据进行缓存

  ②如果要强制将缓存数据写入设备可调用FlushFileBuffers函数,但要注意该设备要用GENERIC_WRITE标志打开。

(3)同步I/O的取消——CancelSynchronousIo(Vista以上版本才支持)

  ①与Read/WriteFile不同,CreateFile函数本身不能进行异步调用。如果等待时间太长,可以通过CancelSynchronousIo(hThread)来强制取消同步I/O操作并退出等待。

  ②参数hTread是由于等待同步I/O请求完成而被挂起的线程,这个句柄必须使用THREAD_TERMINATE访问权限创建,否则调用CancelSynchronousIo函数会失败。

  ③当调用CreateThread或_beginthreadex创建线程时,如果安全属性设为NULL,那么默认的权限是THREAD_IMPERSONATE

  ④当线程因等待同步I/O而被挂起,如果使用CancelSynchronousIo唤醒该线程,并取消同步操作。同时返回TRUE,但GetLastError将返回ERROR_OPERATION_ABORTED。

  ⑤调用CancelSynchronousIo的线程并不知道要唤醒的另一个线程目前的状态,如果这时另一个线程并不是因为要等待设备应被挂起,那么CancelSyncronousIo会返回FALSE,这时GetLastError将得到ERROR_NOT_FOUND。

10.4 异步设备I/0基础

10.4.1 OVERLAPPED结构

(1)异步访问设备的方法

  ①先将CreateFile函数里的dwFlagsAndAttributes中指定为FILE_FLAG_OVERLAPPED标志,以告诉系统我们要以异步的方式来打开设备,以便后继的访问。

  ②调用Read/WriteFile并设置pOverlapped参数,将I/O请求包加入设备驱动程序的队列中。(注意,I/O请求包被发往驱动程序的队列。完成端口的队列是用来接收I/O完成包的,也就是说它们是两个不同的队列。特别是当设备关联了完成端口以后很容易混淆!)。

(2)OVERLAPPED结构体

字段

描述

DWORD Internal

[out]出错代码

①当我们发出异步I/O请求时,会被设为STATUS_PENDING,表示没有错误,操作即将开始(或尚未开始),也叫作请求还处在等待状态。

②可用HasOverlappedIoComplete(pOverlapped)宏来检查是否还在等待状态。

DWORD InternalHigh

[out]己传输的字节数。当异步I/O请求完成时,用来保存己传输的字节数。

DWORD Offset

DWORD OffsetHigh

[in]文件指针,偏移(分别是低32位和高32位),表示访问文件时从哪里开始进行I/O操作。

①设置异步时,会忽略文件内核对象的文件指针,因为那是给同步操作使用的

②非文件设备会忽略OffSet和OffSetHigh,但初始化时仍须指定为0

HANDLE hEvent

[in]事件句柄或自定义C++对象的地址,用来接收I/O完成时的通知。(见后面的分析)

10.4.2 异步设备I/O的注意事项

(1)设备驱动程序不必以先入先出的方式来处理队列中的I/O请求。这是因为在执行I/O请求时,为了提高性能(如降低磁头的移动和寻道时间,文件系统的驱动程序可能会在I/O请求队列中寻找那些要访问的位置在物理硬盘中相邻的请求)。

ReadFile(hFile,bBuffer,100,NULL,&o1); //读请求先入列,并不一定先被处理。

WriteFile(hFile,bBuffer,100,NULL,&o2);//写请求后入列,也可能被先处理。

(2)错误的检查

  ①异步I/O以同步方式执行

    A、由于存在高速缓存,当试图将一个异步I/O请求入列时,设备驱动程序可能会直接从缓存中获取数据,而无需将I/O请求入列,这叫同步方式来执行该操作。

    B、同步方式执行时,Read/WriteFile这时己经从缓存中获得数据,会返回成功(非零)

  ②异步I/O以异步方式执行:错误时会返回FALSE,GetLastError得到的常见错误如下

错误码

描述

ERROR_IO_PENDING

I/O请求己经被成功加入到了队列,会在晚些时候完成(其实并没错误产生)

ERROR_INVALID_USER_BUFFER

ERROR_NOT_ENOUGH_MEMORY

I/O队列列表己满。新I/O请求无法加入队列。

ERROR_NOT_ENOUGH_QUOTA

(Quota限额的意思)

某些设备要求将我们的数据缓存所在的存储器页面锁定,这样当I/O在等待处理的时候,数据不会被换出内存。系统对一个进程能够锁定的存储器页面数量是有做了限制,如果在该进程线程中调用的Read/WriteFile要锁定的那缓存超过限制,就会返回FALSE。这里可以调用SetProcessWorkingSetSize给进程增加配额。

(3)异步I/O请求完成之前,一定不能移动或销毁发出I/O请求时所使用的Buffer和OVERLAPPED结构体。如下以的代码是错误的。

void ReadData(HANDLE hFile){

  OVERLAPPED ol={};

  BYTE b[];

  ReadFile(hFile,b,,NULL,&ol); //异步调用。结构体ol和缓存b是局部变量,被销毁。但I/O请求完成后,驱动程序并没意识到ReadData己经返回,会修改ol和b指向的栈内存,从而破坏那里的数据。
}

10.4.3 取消队列中的设备I/O请求——在I/O请求加入队列后,处理前将其取消

(1)CancelIo(hFile)取消由调用该函数的线程发往hFile这个设备的所有I/O请求。(除非设备己经关联到I/O完成端口,因为这时I/O请求被发往的是完成端口的队列)。

(2)关闭设备句柄(如CloseHandle(hFile)来取消己经添加到队列中的所有I/O请求。而不管这个I/O是哪个线程添加的。

(3)当线程终止时,会自动取消该线程发出的所有I/O请求。但如果请求被发往的是I/O完成端口,那么它们不在被取消之列。

(4)CancelIoEx(hFile,pOverlapped)可用来取消发往hFile设备的待处理I/O请求不管是哪个线程发往这个设备的),该函数每次只取消一条由pOverlapped指定的待处理请求,如果pOverlapped为NULL,则取消所有待处理的I/O请求

★被取消的I/O请求会导致Read/WriteFile失败,通过GetLastError时会返回错误码ERROR_OPERATION_ABORTED

第10章 同步设备I/O和异步设备I/O(2)_同步IO和异步IO基础的更多相关文章

  1. USB 3.0规范中译本 第10章 集线器,主机下行口以及设备上行口规范

    本文为CoryXie原创译文,转载及有任何问题请联系cory.xie#gmail.com. 本章描述USB 3.0 集线器的体系结构要求.本章还描述主机下行口和集线器下行口之间功能性的不同之处,以及设 ...

  2. Windows核心编程:第10章 同步设备IO与异步设备IO

    Github https://github.com/gongluck/Windows-Core-Program.git //第10章 同步设备IO与异步设备IO.cpp: 定义应用程序的入口点. // ...

  3. 第10章 同步设备I/O和异步设备I/O(3)_接收I/O请求完成通知的4种方法

    10.5 接收I/O请求完成的通知 (1)I/O请求被加入设备驱动程序的队列,当请求完成以后,设备驱动也要负责通知我们I/O请求己经完成. (2)可以用4种方法来接收I/O请求己经完成的通知 技术 特 ...

  4. 第10章 同步设备I/O和异步设备I/O(1)_常见设备及CreateFile函数

    10.1 打开和关闭设备 10.1.1 设备的定义——在Windows中可以与之进行通信的任何东西. (1)常见设备及用途 设备 用途 用来打开设备的函数 文件 永久存储任何数据 CreateFile ...

  5. windows核心编程---第九章 同步设备IO与异步设备IO之同步IO

    同步设备IO 所谓同步IO是指线程在发起IO请求后会被挂起,IO完成后继续执行. 异步IO是指:线程发起IO请求后并不会挂起而是继续执行.IO完毕后会得到设备的通知.而IO完成端口就是实现这种通知的很 ...

  6. 高性能Linux服务器 第10章 基于Linux服务器的性能分析与优化

    高性能Linux服务器 第10章    基于Linux服务器的性能分析与优化 作为一名Linux系统管理员,最主要的工作是优化系统配置,使应用在系统上以最优的状态运行.但硬件问题.软件问题.网络环境等 ...

  7. Linux就这个范儿 第10章 生死与共的兄弟

    Linux就这个范儿 第10章 生死与共的兄弟 就说Linux系统的开机.必须经过加载BIOS.读取MBR.Boot Loader.加载内核.启动init进程并确定运行等级.执行初始化脚本.启动内核模 ...

  8. 第10章 系统级I/O

    第10章 系统级I/O 10.1 Unix I/O 一个Unix文件就是一个m个字节的序列:B0,B1,…,BK,…,Bm-1 Unix I/O:一种将设备优雅地映射为文件的方式,允许Unix内核引出 ...

  9. JavaScript高级程序设计(第三版)学习笔记8、9、10章

    第8章,BOM BOM的核心对象是window,具有双重角色,既是js访问浏览器的一个接口,又是ECMAScript规定的Global对象.因此,在全局作用域中声明的函数.变量都会变成window对象 ...

随机推荐

  1. SDWebImage 加载网络图片失败,重新运行,就能加载成功。

    现象: 使用SDWebImage 加载网络图片,偶尔会有一两张图片就是显示不出来.重新运行有时又可以了. 这个问题的原因是: 当SDWebImage 在加载图片的时候 我用的是- (void)sd_s ...

  2. [web安全]Web应用漏洞攻击分析与防范

    网站攻击主要分为以下几类: (1) sql注入攻击 SQL Injection:就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令.它是利 ...

  3. 服务 {49A27252-A326-4EF1-B698-6EBC7068833C} 的计时器作业 id {573BE459-DF82-481C-84BD-CA14D287450B} 配置刷新的上一个实例仍在运行,因此将跳过当前的实例。请考虑增加作业之间的时间间隔。

    在SharePoint2007的错误日志中发现大量如下错误: 07/02/2013 16:17:25.99     OWSTIMER.EXE (0x0958)     0x097C    Window ...

  4. ios7 tableview被navigationbar挡住

    用ego下拉刷新的时候,每次在ios7时,tableview都会上移...导致被navagationbar挡住.ios6是正常的,于是在init的时候添加如下代码... NSComparisonRes ...

  5. Android悬浮窗实现 使用WindowManager

    Android悬浮窗实现 使用WindowManager WindowManager介绍 通过Context.getSystemService(Context.WINDOW_SERVICE)可以获得  ...

  6. iOS 开发之路(登陆验证调用WebService)二

    swift3.0下使用Alamofire调用Webservice遇到的一些问题以及解决方案. 首先是针对没有证书的https下的接口处理问题(ps:不推荐在正式版本中使用),manager.reque ...

  7. iOS FMDB的使用(增,删,改,查,sqlite存取图片)

    iOS FMDB的使用(增,删,改,查,sqlite存取图片) 在上一篇博客我对sqlite的基本使用进行了详细介绍... 但是在实际开发中原生使用的频率是很少的... 这篇博客我将会较全面的介绍FM ...

  8. 截取UIImage指定大小区域

    截取UIImage指定大小区域 最近遇到这样的需求:从服务器获取到一张照片,只需要显示他的左半部分,或者中间部分等等.也就是截取UIImage指定大小区域. UIImage扩展 我的解决方案是对UII ...

  9. 学习Coding-iOS开源项目日志(一)

    前言:作为初级程序员,想要提高自己的水平,其中一个有效的学习方法就是学习别人好的项目.本篇开始会陆续更新本人对github上开源的一个很不错的项目的一点点学习积累.也就是,探究着别人写的源码,我学到了 ...

  10. zend studio 9.0.4 破解、汉化和字体颜色及快捷键相关设置

    转载:http://www.penglig.com/post-45.html 下载:http://www.geekso.com/component/zendstudio-downloads/ 破解:h ...