同步异步设备IO1

上传人:仙*** 文档编号:181879907 上传时间:2023-01-18 格式:DOC 页数:8 大小:68KB
收藏 版权申诉 举报 下载
同步异步设备IO1_第1页
第1页 / 共8页
同步异步设备IO1_第2页
第2页 / 共8页
同步异步设备IO1_第3页
第3页 / 共8页
资源描述:

《同步异步设备IO1》由会员分享,可在线阅读,更多相关《同步异步设备IO1(8页珍藏版)》请在装配图网上搜索。

1、设备I/O的同步与异步一、 概述Windows的优势之一是它支持大量的设备类型,这里我们将设备笼统的定义为能够与之通信的任何东西,常见的一些设备及打开方式有:设备打开设备的函数文件CreateFile()目录同上逻辑磁盘驱动器同上物理磁盘驱动器同上串口同上并口同上邮件槽服务器CreateMailslot()邮件槽客户端CreateFile()命名管道服务器CreateNamedPipe()命名管道客户端CreateFile()匿名管道CreatePipe()套接字Socket()控制台CreateConsoleScreenBuffer() CreateStdHandle()当然,这里只是简单地

2、列出了各个设备打开的API,具体用法参数可以查阅MSDN或者SDK。当线程与设备发生通信时,即线程发出设备I/O请求时,一般来说有两种方式:同步设备I/O请求:字如其名,线程发出设备I/O请求后,它会被临时挂起,直到设备完成I/O请求为止,显然这种方式严重损坏性能;异步设备I/O请求:线程发出设备I/O请求后,不会被临时挂起而是继续执行其他任务,而设备同时继续处理I/O请求,设备处理完成后发送信号给线程,线程接着处理I/O结果。异步设备I/O可以避免线程挂起导致的CPU大量闲置,提高了利用率和吞吐量。与设备I/O的通信交互是Windows编程中的重点,涉及到诸多的线程的同步方式,尤其是I/O完

3、成端口的引入,使得不管是否与设备I/O关联,都提供了一种有无数种用途的绝佳的线程间通信机制。囿于学力,很多部分的理解都很有限,把自己掌握的整理出来,以便日后再学习吧。这篇笔记的结构大致如下: 打开和关闭设备 使用文件设备 异步设备I/O基础 接收I/O请求完成通知二、 打开和关闭设备为了执行任何类型的设备I/O,我们必须先打开想要操作的设备并得到一个句柄,随后我们可以讲该句柄传给许多函数来与设备进行通信。这里同样用这个设备句柄来唯一标识我们的设备。HANDLE CreateFile(PCTSTR pszName,DWORD dwDesiredAccess,DWORD dwShareMode,P

4、SECURITY_ATTRIBUTES psa,DWORD dwCreationDisposition,DWORD dwFlagsAndAttributes,HANDLE hFileTemplate);从之前的表中也可以看出,CreateFile是打开许多设备句柄的关键函数,所以我们对它的参数做一个具体的说明。l pszName:既可以标识设备的类型,也可以表示该类设备的某个实例。l dwDesiredAccess:用来指定我们相用什么样的方式来和设备进行数据传输,常见的有四个标志,它们是0表示我们不希望对设备读出或写入任何数据,一般用来只想改变设备的配置(比如修改文件的时间戳)GENERIC

5、_READ允许对设备进行只读访问GENERIC_WRITE允许对设备进行只写访问,比如备份软件或者将数据发送到打印机GENERIC_READ | GENERIC_WRITE允许对设备进行读写操作l dwShareMode:用来指定设备共享特权(device-sharing privilege),但我们打开一个设备但是尚未调用CloseHandle()关闭时,该参数可以控制其他的CreateFile()调用以何种方式打开设备。常见参数有0要求独占对设备的访问FILE_SHARE_READ只允许共享设备读取方式FILE_SHARE_WRITE只允许共享设备写入方式FILE_SHARE_READ |

6、 FILE_SHARE_WRITE不解释FILE_SHARE_DELETE对文件操作时我们不关心文件是否被逻辑删除或者被移动,先将文件打上待删除标记,只有当该文件打开的所有句柄都被关闭的时候再将其真正删除l Psa指向一个内核对象都具备的安全属性结构,里面可以指定安全信息以及我们是否希望CreateFile返回的句柄能被继承。通常我们传入NULL,这表示用默认的安全设定来创建文件,并且返回的句柄是不可继承的。l dwCreationDisposition:用来表示用CreateFile打开文件时如果碰到存在的同名文件等情况如何处理,如CREATE_NEW若存在同名文件,则调用失败CREATE_

7、ALWAYS若存在同名文件,则覆盖OPEN_EXISTING若打开的文件或者设备不存咋则调用失败OPEN_ALWAYS若打开文件不存在则只直接创建一个当调用CreateFile打开文件之外的其他设备时,必须将OPEN_EXISTING传给dwCreationDisposition参数l dwFlagsAndAttributes:允许我们设置一些标志来微调与设备之间的通信;其次我们还可以通过一些属性参数来设置文件属性。比如常见的告诉缓存标志:FILE_FLAG_NO_BUFFERING告诉高速缓存管理器我们不希望它对任何数据进行缓存,我们会自己对数据进行缓存;标志FILE_FLAG_DELETE

8、_ON_CLOSE可以让文件系统在文件的所有句柄都被关闭后删除该文件(比如程序运行用到的临时文件,结束后删除,更加隐蔽),标志FLIE_FLAG_BACKUP_SEMANTICS用于备份和恢复软件,不要求文件的全部管理员权限,还有一个重要的标志FILE_FLAG_OVERLAPPED告诉系统我们想要以异步方式来访问设备,默认是同步I/O访问请求。我们重点来介绍一下文件属性参数,可以看到常见的Windows文件属性都有涉及FILE_ATTRIBUTE_ARCHIVE存档文件,默认自动设置FILE_ATTRIBUTE_ENCRYPTED加密文件FILE_ATTRIBUTE_HIDDEN隐藏文件FI

9、LE_ATTRIBUTE_NORMAL没有其他属性,只有单独使用时才有效FILE_ATTRIBUTE_SYSTEM系统文件FILE_ATTRIBUTE_READONLY只读文件OK,可以看到右键文件属性的所有可能这里基本都有涉及,尽管没有向Linux那样提供了丰富的命令行选项,但是Windows在API参数中也为我们提供了尽可能多的功能选项。三、 使用文件设备文件的使用非常普遍,因此重点来讨论下与文件设备有关的问题。首先我们看看如何取得文件的大小。BOOL GetFileSizeEx( HANDLE hFile, PLARGE_INTEGER pliFileSize /联合类型指针);hFil

10、e当然就是目标文件的句柄了,pliFileSize是一个LARGE_INTEGER联合类型的地址,这个联合体允许我们以一个64位的有符号数的形式来引用一个64位有符号数,或者以两个32位值的形式来引用一个64位有符号数。下面是大概的定义:Typedef union _LARGE_INTEGER Struct DWORD LowPart; /Low 32-bit unsigned value LONG HighPart; /High 32-bit signed value; LONGLONG QuadPart; /Full 64-bit signed value LARGE_INTEGER, *

11、PLARGE_INTEGER;我们调用GetFileSizeEx可以得到文件的逻辑大小,使用GetCompressedFileSize可以得到文件压缩后的物理大小。如果要对一个文件读写,其实就是向文件发送一个I/O请求,当然,这里的道理其实不仅适用于文件,对于设备同样适用,如邮件槽、管道、套接字等等。我们通常使用如下函数发送I/O请求,BOOL ReadFile( HANDLE hFile, PVOID pvBuffer, DWORD nNumBytesToRead, PDWORD pdwNumBytes, OVERLAPPED* pOverlapped);BOOL WriteFile( HA

12、NDLE hFile, CONST VOID *pvBuffer, DWORD nNumBytesToWrite, PDWORD pdwNumBytes, OVERLAPPED* pOverlapped);执行同步I/O时pOverlapped设为NULL,只有在异步I/O时才有意义。每当调用CreateFile时系统会创建一个文件内核对象来管理对文件的操作,在这个内核对象中维护这一个文件指针,它指向一个64位的偏移量,表示应该在哪里执行下一次同步读取或写入操作,我们称之为文件指针,初始化为0。需要注意的是,调用CreateFile打开同一个文件会得到多个文件内核对象,内部维护的文件指针彼此独

13、立。我们可以使用SetFilePointerEx来设置文件指针的位置BOOL SetFilePointerEx( HANDLE hFile, LARGE_INTEGER liDistanceToMove, PLAGER_INTEGER pliNewFilePointer, DWORD dwMoveMethod);hFile表示我们想要修改哪个文件内核对象的文件指针。liDistanceToMove告诉系统我们想要移动把指针在dwMoveMethod指定的位置移动多少个字节。使用负数可以将文件指针向后移动。dwMoveMehtod告诉系统如何解释liDistanceToMove,比如常用的参数值

14、为FILE_BEGIN从文件头开始计算liDistanceToMove,之和为当前的文件指针FILE_CURRENT从当前的文件指针位置开始计算FILE_END在文件末尾开始计算我们给出一个小例子/本程序用来实验联系Windows关于文件读写操作的API/命令行启动,参数作为写入文件的内容#include #include #include #include using namespace std;int main(int argc, char *argv)/操作一个文件之前必须先调用CreateFile()函数以指定的方式打开一个文件/访问方式:GENERIC_READ |GENERIC_W

15、RITE/共享模式:当文件被打开时,其他程序可以对该文进进行的操作,表示不允许同时对任何操作/创建方式:当文件存在或者不存在时的处理策略CREATE_ALWAYS, CREATE_NEW, OPEN_ALWAYS, OPEN_EXISTING/新创建的文件属性:ARCHIVE(存档),HIDDEN, SYSTEM, READONLY/模板文件:没有则设为NULLHANDLE hFile;hFile = CreateFile(LC:Documents and Settingsadmin桌面FileAPITest.txt, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS,

16、FILE_ATTRIBUTE_HIDDEN, NULL);if (hFile = INVALID_HANDLE_VALUE)coutCreateFile error !endl;return -1;/调用SetFilePointer()函数凋整文件指针位置,移动到文件指定位置:FILE_BEGIN, FILE_CURRENT, FILE_END/第二/三个参数指定在指定文件指针处移动到位置大小if (SetFilePointer(hFile, 0, NULL, FILE_END) = -1)coutSetFilePointer error !endl;return -2;/利用WriteFil

17、e()函数将命令行的参数内容写入到指定的文件中DWORD dwByteWritten; /实际写入的字节数if (WriteFile(hFile, argv1, strlen(argv1), &dwByteWritten, NULL) = FALSE)coutWriteFile error !endl;return -3;cout写入数据成功!endl;/使用完毕后释放文件句柄CloseHandle(hFile);return 0;/*PS:其他的相关函数:写入函数ReadFile()复制函数CopeFile()移动函数MoveFile()删除函数DeleteFile(LPCTSTR lpFi

18、leName);本函数用来生成了一个隐藏文件*/四、 异步设备I/O基础对于异步设备而言,线程访问I/O设备大致步骤如下:1. 线程调用CreateFile(.,FILE_FLAG_OVERLAPPED,.)以异步方式打开一个文件设备,调用ReadFile/WriteFile发送异步I/O请求;2. 设备驱动将I/O请求加入等待队列,线程继续执行;3. 设备执行完I/O请求返回给设备驱动程序,设备驱动发送信号给线程4. 线程继续执行I/O处理线程将I/O请求加入设备等待队列的方法我们已经明白了,但是设备驱动如何告知线程I/O请求处理完毕呢?比着急,我们先来学习一下异步设备I/O的基本知识。我们

19、已经知道,如果想异步访问一个I/O设备,必须首先用CreateFile()传入FILE_FLAG_OVERLAPPED参数打开一个设备句柄,然后调用ReadFile/WriteFile将I/O请求加入设备驱动程序的队列中。这里涉及到一个OVERLAPPED结构体,到底是怎么一回事呢?Typedef struct _OVERLAPPED DWORD Internal; / out Error Code DWORD InternalHigh; / out Number of bytes transferred DWORD Offset; / in Low 32-bit file offset DW

20、ORD OffsetHigh; / in High 32-bit file offset HANDLE hEvent; / in Event handle or data OVERLAPPED, *LPOVERLAPPED;这里标注out的是在设备处理完I/O请求后添加的,不需要我们负责;我们需要初始化标注为in的三个参数。两个32位偏移量共同组成文件的64位偏移量,用来指定文件的文件指针位置,对于非文件设备Offset和OffsetHigh必须初始化为0,因为非文件设备不需要文件指针。使用异步设备I/O时我们有以下需要注意的问题:1. 设备驱动程序不必以先入先出的方式来处理队列中的I/O请求

21、2. 如果以同步方式执行ReadFile/WriteFile,成功则返回非零值,失败返回FALSE;如果以异步方式执行,执行成功也会返回FALSE,利用GerLastError可以查看错误代码ERROR_IO_PENDING则表示异步I/O请求已被成功加入了队列,会在晚些时候执行。3. 在异步I/O请求完成前,一定不能移动或是销毁在发出I/O请求时所使用的数据缓存和OVERLAPPED结构。4. 我们必须为每一个I/O请求分配并初始化一个不同的OVERLAPPED结构五、 接收I/O请求完成通知这部分内容主要回到设备驱动如何告知线程I/O处理完的问题。Windows提供了四种方法,由易到难是触

22、发设备内核对象;触发事件内核对象;可提醒I/O;I/O完成端口。应该说,I/O完成端口属于目前最完美的技术,但是对于当前自己的程序而言不需要,所以只需要使用简单的设备内核对象或者事件内核对象就可以实现设备I/O请求的送达。l 触发设备内核对象由于文件本身即是一种内核对象,触发规则为:有待处理的I/O请求时为未触发状态,I/O请求处理完成时为触发状态。因而我们只需要使用WaitForSingleObject(hFile, INFINITE)一个语句即可,当然这个语句要放到一定代码之后,估计I/O请求处理完毕之后再进入检查文件是否触发。我们给出一个示例代码HANDLE hFile = Create

23、File(., FILE_FLAG_OVERLAPPED, .);BYTE bBuffer100;OVERLAPPED ol = 0;ol.Offset = 345;BOOL bReadDone = ReadFile(hFile, bBuffer, 100, NULL, &ol);DWORD dwError = GetLastError();If (!bReadDone & (dwError = ERROR_IO_PENDING) ) WaitForSingleObject(hFile, INFINITE); bReadDone = TRUE;l 触发事件内核对象只需要将文件内核对象改为事件内

24、核对象就可以了,这里需要注意的是此时OVERLAPPED结构的最后一个成员hEvent需要和我们的事件内核对象绑定起来,我们给出一个方法来同时执行多个异步设备I/O操作并使用同一个设备对象。HANDLE hFile = CreateFile(., FILE_FLAG_OVERLAPPED, .);BYTE bReadBuffer10;OVERLAPPED oRead = 0;oRead.Offset = 0;oRead.hEvent = CreateEvent(.);ReadFile(hFile, bReadBuffer, 10, NULL, &oRead);BYTE bWriteBuffer

25、10 = 0, 1,2, 3, 4, 5, 6, 7, 8, 9;OVERLAPPED oWrite = 0;oWrite.Offset = 0;oWrite.hEvent = CreateEvent(.);WriteFile(hFile, bWriteBuffer, _countof(bWriteBuffer), NULL, &oWrite);. . .HANDLE h2;H0 = oRead.hEvent;H1 = oWrite.hEvent;DWORD dw = WaitForMultipleObjects(2, h, FALSE, INFINITE);Switch (dw - WAIT_OBJECT_0)Case 0: /Read completedbreadk;Case 1: /Write completedBreak;

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!