第10章 同步设备I/O和异步设备I/O(1)_常见设备及CreateFile函数
10.1 打开和关闭设备
10.1.1 设备的定义——在Windows中可以与之进行通信的任何东西。
(1)常见设备及用途
|
设备 |
用途 |
用来打开设备的函数 |
|
文件 |
永久存储任何数据 |
CreateFile(pszName为路径名或UNC路径名) |
|
目录 |
属性和文件压缩的设置 |
同上,如果指定FILE_FLAG_BACKUP_SEMANTICS标志,将打开一个目录。可以改变目录的属性(如正常或隐藏等)和他们的时间戳 |
|
逻辑磁盘驱动器 |
格式化驱动器 |
CreateFile(pszName为\\.\x:)其中的x是驱动器的盘符。可以用来格式化驱动器或检测驱动器媒介的大小 |
|
物理磁盘驱动器 |
访问分区表 |
CreateFile(pszName为\\.\PHYSICALDRIVEx:)打开物理驱动器中,其的x是物理驱动器的盘符。如\\.\PHYSICALDRIVE0,表示第一个物理驱动器 |
|
串口 |
通过电话线传输数据 |
CreateFile(pszName为"COMx") |
|
并口 |
将数据传输至打印机 |
CreateFile(pszName为"LPTx") |
|
邮件槽 |
一对多数据传输,通常是通过网络传到另一台运行的Windows的机器 |
邮件槽服务器:CreateMailslot(pszName为"\\.\mailslot\mailslotname") 邮件槽客户端:CreateMailslot(pszName为"\\servername\mailslot\mailslotname") |
|
命名管道 |
一对一数据传输,通常是通过网络传到另一台运行Windows的机器上 |
服务器端:CreateNamePipe(pszName为 "\\.\pipe\pipename") 客户端:CreateFile(pszName为 "\\servername\pipe\pipename") |
|
匿名管道 |
单机上的一对一数据传输(绝不会跨网络) |
CreatePipe用来打开服务器和客户端 |
|
套接字 |
报文或数据流的传输,通常是通过网络传到任何支持套按字的机器上(机器不一定要运行Windows操作系统 |
Socket、accept或AcceptEx |
|
控制台 |
文本窗口中的屏幕缓存 |
CreateConsoleScreenBuffer或GetStdHandle |
(2)设置与设备通信的参数,如SetCommConfig设置串口的波特率;SetMailslotInfo设置超时邮件槽的超时值。
(3)关闭通信:对于大多数设备,调用CloseHandle即可,但套接字用closesocket
(4)获取设备的类型:GetFileType,返回值如下
①FILE_TYPE_UNKNOWN:未知类型 ②FILE_TYPE_DISK:磁盘文件
③FILE_TYPE_CHAR:字符文件,一般指并口并设备或控制台
④FILE_TYPE_PIPE:命名管道或匿名管道
10.1.2 细看CreateFile
(1)CreateFile函数
|
参数 |
描述 |
|
pszName |
既可以是设备的类型,也可表示该类设备的某个实例 |
|
dwDesiredAccess |
数据传输的方式 0:只能改变设备的配置,不能读取数据或写入数据 GENERIC_READ:允许对设备进行只读访问 GENERIC_WRITE:只写访问(注意不可读) GENERIC_READ|GENERIC_WRITE:可读可写 |
|
dwShareMode |
指定设备的共享特权 ①0:独占对设备的访问。如果设备己经打开,CreateFile调用会失败。同样,如果我们成功打开设备,那样后续的CreateFile会失败。 ②FILE_SHARE_READ:只共享读(不能修改设备的数据) A、如果设备己被只写或独占方式打开,则我们的CreateFile会失败。 B、如果我们成功打开,则后续的使用GENERIC_WRITE调用CreateFile会失败。 ②FILE_SHARE_WRITE:只共享写(不能读取设备的数据) A、如果设备己被只读或独占方式打开,则我们的CreateFile会失败。 B、如果我们成功打开,则后续的使用GENERIC_READ调用CreateFile会失败。 ③FILE_SHARE_WRITE|FILE_SHARE_READ:共享读写 A、如果设备己被独占方式打开,则我们的CreateFile会失败。 B、如果我们成功打开,则后续的要求独占读取(即有dwShareMode=0, dwDesiredAccess=GENERIC_READ)、独占写入或独占读写调用CreateFile会失败。 ④FILE_SHARE_DELETE:此时当删除或移动文件时会标志为待删除,当所有打开的句柄都被关闭时,才真正的删除。 |
|
psa |
安全属性,通常设为NULL,默认时返回的句柄是不可继承的。 |
|
dwCreateDisposition |
对文件的意义比其他设备的类型更大 CREATE_NEW:创建新文件,如果存在同名文件,CREATEFILE失败 CREATE_ALWAYS:无论是否存在同名,都创建一个新文件,被覆盖旧文件 OPEN_EXISTING:打开己有的文件或设备,如果不存在,CREATEFILE失败。如果是打开文件之外的设备,必须设置该标志。 OPEN_ALWAYS:如果文件己存在,直接打开。如果不存在,则先创建再打开。 TRUNCATE_EXISITING:打开己有的文件并将文件大小截断为0 |
|
dwFlagsAndAttributes |
用于微调与设备之间的通信(如果是文件,则设置文件的属性)(见后面第2点的分析) |
|
hFileTemplate |
可以为NULL,也可以是一个文件句柄 ①如果hFileTemplate标识一个文件句柄,则dwFlagsAndAttributes参数会被忽略,转而使用hFileTemplate模板文件的属性,但此时hFileTemplate必须先以GENERIC_READ打开。 ②如果CreateFile要打开而不是创建新文件时,则hFileTemplate被忽略 |
|
返回值 |
成功:返回文件或设备句柄 失败:INVALID_HANDLE_VALUE(-1),注意不是NULL! |
(2)dwFlagsAndAttributes参数的详细分析
①CreateFile的高速缓存标志
|
参数 |
描述 |
|
FILE_FLAG_NO_BUFFERING |
表示访问文件时不使用数据高速缓存技术,这时数据会直接写入我们提供的缓冲中,因直接读写磁盘,所以必须遵循一定的规则: ①在访问文件的时候,使用的偏移量必须正好是磁盘卷扇区大小的整数倍。(可用GetDiskFreeSpace来确定扇区的大小) ②读取/写入文件的字节数必须正好是扇习大小的整数倍。 ③必须确保我们的缓存在进程地址空间中的起始地址正好是扇区大小的整数倍。 |
|
FILE_FLAG_SEQUENTIAL_SCAN |
①只有允许对文件数据进行缓存时,这个标志才有用。否则被忽略 ②读取文件时,系统会顺序访问文件,因使用了高级缓存技术,所以每次读取的数据量可能会超过我们要求的数量。此时如果重新设置文件指针,那缓存中的数据就浪费了。如果我们必须经常自己设置文件指针,可以指定FILE_FLAG_RANDOM_ACCESS,告诉系统不要提前读取文件数据。 ③文件越大,高速缓存器为分件分配的缓存就越大。从而可能导致的打开文件失败。 |
|
FILE_FLAG_WRITE_THROUGH |
写入时,禁止对文件进行缓存。即系统会将所有对文件的修改直接写入磁盘。但是系统仍然会在内部的缓存中保存文件的数据。 |
②CreateFile的其他标志
|
参数 |
描述 |
|
FILE_FLAG_DELETE_ON_CLOSE |
让文件在所有的句柄都被关闭后,删除该文件。这个标志通常与FILE_ATTRIBUTE_TEMPORARY属性一起使用。即会创建一个临时文件,并在关闭的时候自动删除该文件。 |
|
FILE_FLAG_BACKUP_SEMANTICS |
备份与恢复软件时,会检查调用线程的访问令牌是否具备对文件或目录的备份/恢复特权,如果有才能打开该文件。因为 |
|
FILE_FLAG_POSIX_SEMANTICS |
在POSIX(非Windows系统)的子系统要求在查找文件名的时区分大小写。 |
|
FILE_FLAG_OPEN_REPARSE_POINT |
告诉系统忽略文件的重解析属性(不推荐使用该标志) |
|
FILE_FLAG_OPEN_NO_RECALL |
当文件长时间没被访问时,系统会将文件内容移到脱机存储器(如磁带中),从而腾出硬盘空间,当文件被打开时,会从磁带恢复到磁盘。该标志禁用这种行为。 |
|
FILE_FLAG_OVERLAPPED |
以异步方式来访问设备(默认时的同步方式打开设备的) |
③文件属性的标志——创建新文件时(不适应用其他类型的设备)
|
参数 |
描述 |
|
FILE_ATTRIBUTE_ARCHIVE |
存档文件,用来将文件标志为“待备份”或“待删除”,当CreateFile创建新文件时,会自动设置这个标志。 |
|
FILE_ATTRIBUTE_ENCRYPTED |
文件是经过加密的 |
|
FILE_ATTRIBUTE_HIDDEN |
隐藏文件 |
|
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED |
内容索引服务不会对文件进行索引 |
|
FILE_ATTRIBUTE_OFFLINE |
文件虽然存在,但文件内容己被转移到脱机存储器中。 |
|
FILE_ATTRIBUTE_READONLY |
只读文件 |
|
FILE_ATTRIBUTE_SYSTEM |
文件是操作系统的一部分,或专供操作系统使用 |
|
FILE_ATTRIBUTE_TEMPORARY |
临时文件 ①CreateFile会将文件的数据尽量保存的内存中,而不是磁盘上。直至无法继续保存在内存中,才被迫写入硬盘。 ②如果没有指定FILE_FLAG_DELETE_ON_CLOSE将在关闭文件时,会将文件在缓存中的数据写入磁盘。否则会被删除掉。 |
10.2 使用文件设备
10.2.1 获取文件的大小
(1)GetFileSizeEx(hFile,pliFileSize)——返回文件的逻辑大小
①hFile文件句柄
②pliFileSize保存文件大小的LARGE_INTEGER结构体指针(文件大小64位表示),返回的是文件的逻辑大小。如100KB文件压缩后只占85KB。则返回100KB。
(2)GetCompressedFileSize(pszFileName,pdwFileSizeHigh)
①pszFileName:文件名(字符串形式)
②返回压缩后的大小,是文件的物理大小,即实际占用的磁盘空间。如以上例子得到85KB。其中文件大小的低32位是函数的返回值,高32位保存在pdwFileSizeHigh中
ULARGE_INTEGER ulFileSize; //64位
ulFileSize.lowPart=GetCompressedFileSize(TEXT("SomFile.dat"),&ulFileSize.HighPart);
10.2.2 设置文件指针的位置
(1)文件内核对象内部有一个文件指针,是一个64位偏移量,用来表示下一次同步(注意:异步操作时必须自己维护的一个OVERRLAPPED结构体,里面包含该信息)读取或写入操作时的位置。
(2)SetFilePointerEx函数——用来设置文件指针
|
参数 |
描述 |
|
HANDLE hFile |
文件句柄 |
|
LARGE_INTEGER liDistanceToMove |
指针移动的字节,系统会把这个值与文件指针的当前值相加,使用负数时文件指针向后移动。 |
|
LARGE_INTEGER pliNewFilePointer |
接收新指针的位置 |
|
DWORD dwMoveMethod |
用来指定移动文件指针时的起始位置 FILE_BEGIN:文件指针被为liDistanceToMove的值。 注意这里的liDistanceToMove被解释为无符号值 FILE_CURRENT:文件对象的文件指针+liDistanceToMove 注意这里的liDistanceToMove被解释为有符号值 FILE_END:文件的逻辑大小+liDistanceToMove。 注意这里的liDistanceToMove被解释为有符号值 |
【注意事项】
①当文件指针设为超过文件当前的大小是正当操作。除非在该位置写入数据或调用SetEndOfFile,否则这样做不会增加文件在磁盘上的实际大小
②SetFilePointerEx操作的文件用FILE_FLAG_NO_BUFFERING标志打开时,那么文件指针只能被设置为扇区大小的整数倍。
③Windows没有提供一个GetFilePointerEx函数。但可以向SetFilePointerEx函数的liDistanceToMove参数传为0来达到同样的效果。
10.2.3 设置文件尾SetEndOfFile——可强制使文件变大或变小
(1)根据文件指针当前所在位置来截断文件大小或增大文件大小。
(2)示例代码——强制文件大小设为1024字节
HANDLE hFile = CreateFile(…); LARGE_INTEGER liDistanceToMove = ; SetFilePointerEx(hFile,liDistanceToMove,NULL,FILE_BEGIN); SetEndOfFile(hFile); CloseHandle(hFile);
第10章 同步设备I/O和异步设备I/O(1)_常见设备及CreateFile函数的更多相关文章
- Windows核心编程:第10章 同步设备IO与异步设备IO
Github https://github.com/gongluck/Windows-Core-Program.git //第10章 同步设备IO与异步设备IO.cpp: 定义应用程序的入口点. // ...
- 第10章 同步设备I/O和异步设备I/O(3)_接收I/O请求完成通知的4种方法
10.5 接收I/O请求完成的通知 (1)I/O请求被加入设备驱动程序的队列,当请求完成以后,设备驱动也要负责通知我们I/O请求己经完成. (2)可以用4种方法来接收I/O请求己经完成的通知 技术 特 ...
- 第10章 同步设备I/O和异步设备I/O(2)_同步IO和异步IO基础
10.3 执行同步设备I/O (1)对设备读写操作的函数 ①ReadFile/WriteFile函数 参数 描述 hFile 文件句柄 pvBuffer 指向要接收文件数据的缓冲区或把缓冲区数据写入设 ...
- 第10章 同步设备I/O和异步设备I/O(4)_利用I/O完成端口实现Socket通信
I/O完成端口原理见上一篇(可点击这里) 10.5.4.4 利用I/O完成端口实现Socket通信 (1)Accept和AcceptEx流程的比较 ①采用accept方式的流程示意图如下(普通的阻塞函 ...
- USB 3.0规范中译本 第10章 集线器,主机下行口以及设备上行口规范
本文为CoryXie原创译文,转载及有任何问题请联系cory.xie#gmail.com. 本章描述USB 3.0 集线器的体系结构要求.本章还描述主机下行口和集线器下行口之间功能性的不同之处,以及设 ...
- windows核心编程---第九章 同步设备IO与异步设备IO之同步IO
同步设备IO 所谓同步IO是指线程在发起IO请求后会被挂起,IO完成后继续执行. 异步IO是指:线程发起IO请求后并不会挂起而是继续执行.IO完毕后会得到设备的通知.而IO完成端口就是实现这种通知的很 ...
- 高性能Linux服务器 第10章 基于Linux服务器的性能分析与优化
高性能Linux服务器 第10章 基于Linux服务器的性能分析与优化 作为一名Linux系统管理员,最主要的工作是优化系统配置,使应用在系统上以最优的状态运行.但硬件问题.软件问题.网络环境等 ...
- Linux就这个范儿 第10章 生死与共的兄弟
Linux就这个范儿 第10章 生死与共的兄弟 就说Linux系统的开机.必须经过加载BIOS.读取MBR.Boot Loader.加载内核.启动init进程并确定运行等级.执行初始化脚本.启动内核模 ...
- C# 语言规范_版本5.0 (第10章 类)
1. 类 类是一种数据结构,它可以包含数据成员(常量和字段).函数成员(方法.属性.事件.索引器.运算符.实例构造函数.静态构造函数和析构函数)以及嵌套类型.类类型支持继承,继承是一种机制,它使派生类 ...
随机推荐
- 小数5.2500四舍五入保留1位小数的java算法之一
BigDecimal bd = new BigDecimal(5.2500); BigDecimal a = bd.setScale(1, BigDecimal.ROUND_HALF_UP); dou ...
- windows 端口 任务
- 定制Eclipse IDE之功能篇(一)
上文回顾:定制Eclipse IDE之界面篇 这一篇文章将记录一些Eclipse插件拓展(extension),简单讲述常用拓展的用法,但可能不会那么详细. 我的主要插件的拓展如下: 一.or ...
- JavaScript学习04 对象
JavaScript学习04 对象 默认对象 日期对象Date, 格式:日期对象名称=new Date([日期参数]) 日期参数: 1.省略(最常用): 2.英文-数值格式:月 日,公元年 [时:分: ...
- Android Contextual Menus之一:floating context menu
Android Contextual Menus之一:floating context menu 上下文菜单 上下文相关的菜单(contextual menu)用来提供影响UI中特定item或者con ...
- 操作系统开发系列—12.a.从Loader到内核 ●
Loader要做两项工作,我们先来做第一项,把内核加载到内存: 1.加载内核到内存. 2.跳入保护模式. 首先编译无内核时: nasm boot.asm -o boot.bin nasm loader ...
- App开发流程之右滑返回手势功能续
上一篇记录了利用系统私有变量和方法实现右滑返回手势功能:http://www.cnblogs.com/ALongWay/p/5893515.html 这篇继续记录另一种方案:利用UINavigatio ...
- linux常用命名复习
ubuntu sysv-rc-conf 用来管理自启动项 centos chkconfig 1. ls命令ls命令是列出目录内容(List Directory Contents)的意思.运行它就 ...
- 从技术经理的角度算一算,如何可以多快好省的做个app
[导读]前端时间,一篇“从产品经理的角度算一算,做个app需要多少钱”的文章在网上疯传,可见大家对互联网创业的热情!这次,从一名技术经理的角度再给大家分析一下,如何使用跨平台开发技术为你节省上百万的开 ...
- 见证历史 -- 2013 NBA 热火夺冠之路有感
见证历史-- 2013 NBA 热火夺冠之路有感今年NBA季后赛从第一轮看起,到最终的热火夺冠,应该看得是最爽的一次.但一些情节和细节,回忆起来,深有感悟. 1. 做人要低调詹宁斯豪言演黑八雄鹿本赛季 ...