下面介绍 一下设备和它们最常见的用途:
设备 | 最常见的用途 |
文件 | 任意数据的持久存储 |
目录 | 属性和文件压缩 |
逻辑磁盘 | 格式化 |
物理磁盘 | 分区表访问 |
串行口 | 通过电话线传输数据 |
并行口 | 向打印机传送数据 |
邮件槽 | 一对多的传输数据,通常 通过网络向一台 Windows 机器传输 |
命名管道 | 一对一的传输数据,通常 通过网络向一台 Windows 机器传输 |
无命管道 | 在同一台机器上一对一的 传输数据(从来不经过网络) |
套 接字 | 数据传输的块或流,通常通过网络向任一支持套接字的计算机传输(不一 定是运行 Windows 的机器) |
控制台 | 文本窗口屏幕缓冲区 |
不管你与什么设备通信, Win32 的 读写设备函数都是一样的。
16.1 打开和关闭设备
要进行任何 I/O 操作,必须首先打开所需设备,并得到它的句柄。下表是打开一些设备的方法,
设备 | 打开设备的函数 |
文件 | CreateFile(pszName 是路径名或 UNC 路径名 ) |
目录 | CreateFile(pszName 是目录名或 UNC 目录名,使用 FILE_FLAG_BACKUP_SEMANTICS) |
逻辑磁盘 | CreateFile(pszName 是“ . X: ” ) |
物理磁盘 | CreateFile(pszName 是 “.PHYSICALDRIVEx”) |
串行口 | CreateFile(pszName 是“ COM? ” ) |
并行口 | CreateFile(pszName 是“ LPT? ” ) |
邮件槽服务器 | CreateMailslot(pszName 是“ .mailslotmailslotname ” ); |
邮件槽客户 | CreateFile(pszName 是“ servernamemailslotmailslotname ” ); |
命名管道服务器 | CreateNamedPipe(pszName 是“ .pipepipename ” ); |
命名管道客户 | CreateFile(pszName 是“ servernamepipepipename ” ) |
无命管道客户和服务器 | CreatePipe |
套接字 | Socket 、 accept 、 AcceptEx |
控制台 | CreateConsoleScreenBuffer , GetStdHandle |
所有这些函数标识设备的一个 32 位句柄。
当你完成设备操作后,必须关闭它。对于大多数设备,可以使用 CloseHandle 来关闭。如果是套接 字要使用 int CloseSocket(SOCKET s); 来关闭。
如果你有一个设备的句柄,你可以使用 GetFileType 来得到设备的类型,
DWORD GetFileType(HANDLE hFile); 它返回如下这些值:
标志 | 说明 |
FILE_TYPE_UNKNOWN | 指定的文件类型不清楚 |
FILE_TYPE_DISK | 指定文件是一个磁盘文 件 |
FILE_TYPE_CHAR | 指定文件是一个字符文 件,一般是 LPT 设 备或控制台 |
FILE_TYPE_PIPE | 指定设备是一个命名或 无名管道 |
16.1.1CreateFile函数
HANDLE CreateFile(LPCTSTR pszName,DWORD dwDesiredAccess,DWORD dwShareMode,LPSECURITY_ATTRIBUTES pSecurityAttributes,DWORD dwCreationDistribution,DWORD DWORD dwFlagsAndAttrs,HANDLE hTemplateFile);
注:该函数可以打开文件或创建文件,但是它还可以打开很多其它设 备。
参数说明:
pszName: 用来标识设备类型和设备的某个实例。它最大可以为260外字符长,不过可以通过在路径名前加入“?”来使该长度增加到32000个字符。不过该函数不支持 相对目录,所以不要在路径名里加“. ”或“.. ”。
dwDesiredAccess: 它指出了你想如何传输数据,如下表所示,你可以指定这些值给它,
值 | 说明 |
0 | 你不想读写设备数据。当 你只想改变设备的配置,如:文件的时间戳时,传递0 |
GENERIC_READ | 允许对设备的只读访问 |
GENERIC_WRITE | 允许对设备的只写访问。 |
GENERIC_READ|GENERIC_WRITE | 允许对设备的读写访问。 |
DwShareMode: 它指出了设备共享的权限。在网络中一个设备可以被几台计算机同时访问,或被几个进程同时访问。你必须要确定是否要让其它计算机或进程访问设备的数据。
下表给出了dwShareMode 的可能值,
值 | 说明 |
0 | 你想独占设备的访问 权。如果设备已经被打开,CreateFile失败。 |
FILE_SHARE_READ | 使用设备只读。如果设 备已经被设置成可写,并该设备已经打开,那么CreateFile调用失败。如果打开成功,那么以后以写方式调用 CreateFile将会失败。 |
FILE_SHARE_WRITE | 让设备为只写。如果设 备已经以只读方式打开,那么CreateFile调用失败。如果打开成功,那么将来CreateFile以只读方 式打开时,将会失败。 |
FILE_SHARE_READ|FILE_SHARE_WRITE | 使设备可读可写。如果 设备已经被独占方式打开,那么CreateFile调用失败。如果打开成功,那么以后CreateFile以读写 方式都会调用成功。 |
pSecurityAttributes: 该参数允许你设定设备的关联内核对象的安全信息和返回的句柄是否可继承。如果想使用缺省的安全属性和让句柄不可被子进行继承,可以将该参数设置为 NULL。
dwCreationDistribution的可能取值如下表所示,
值 | 说 明 |
CREATE_NEW | 告 诉CreateFile创建一个新文件,如果已经有同名文件存在,则失败。 |
CREATE_ALWAYS | 告 诉CreateFile不管有没有同名文件存在,都创建一个文件。 |
OPEN_EXISTING | 告 诉CreateFile打开一个已经存在的文件。如果不存在则失败。 |
OPEN_ALWAYS | 告 诉CreateFile打开一个文件,如果不存在,则创建。 |
TRUNCATE_EXISTING | 告 诉CreateFile打开一个已经存在的文件,并将其大小设置成0,如果文件不存在,则失败。 GENERIC_WRITE必须与该标志一起使用。 |
注意:当你使用CreateFile打开的不是文件而是设备时,应当向dwCreationDistribution传递 OPEN_EXISTING标志。
dwFlagsAndAttrs:这个 参数有两个作用,一、它允许你微调同设备的通信,如果是文件的话,你还可以设置文件的属性。
下面先说一下 在访问设备时需要用到的一些“缓存标志”,
1.FILE_FLAG_NO_BUFFERING:该标志告诉缓存管理器,不想让缓存管理器 缓存任何数据,你自己负责缓存数据。如果不指定这个标志,那么系统就会缓存来往于磁盘的数据,这样,如果你从文件中读了几个字节后,又读了几个字节,文件 的数据很可能已经存入内存了,这样只用访问一次磁盘而不是两次,不过,这意味着文件中的数据在内存中保存了两份,也就是说,缓存管理器有一个缓冲区,你调 用的某个函数(ReadFile)从缓存管理器中的缓冲区中向你自己的缓冲区中拷贝了一些数据。指定该标志后,系统会将数据写入你提供的缓冲区,你必须遵 守以下规则:一、你访问文件时使用偏移量必须是磁盘扇区大小的整数倍。二、你读写的字节数必须是扇区大小的整数倍。三、必须保证进程中的缓冲区开始地址必 须是扇区大小的整数倍。
2.FILE_FLAG_SEQUENTIAL_SCAN和 FILE_FLAG_RONDOM_ACCESS这两个标志只有在你允许系统为你缓存数据时才有用,也就是说,在你没有指定标志 FILE_FLAG_NO_BUFFERING时,这两个标志才有用。下面分别说明这两标志,
FILE_FLAG_SEQUENTIAL_SCAN: 它告诉系统你会顺序的访问文件。这时,当你从文件中读数据时,系统实际读的数据要比你要求要读的数据要多。
FILE_FLAG_RONDOM_ACCESS: 该标志告诉系统不要预先读取文件中的数据。
3.FILE_FLAG_WRITE_THROUGH:该标志使文件写的缓冲区无效,以降低数 据丢失的可能性。当这个标志被用于打开网络服务器上的文件时,Win32写文件函数在数据被写到网络服务器的磁盘上之后才返回。
下面说一下其它一些标志:
FILE_FLAG_DELETE_ON_CLOSE: 该标志告诉系统在关闭文件后删除文件。该标志经常同属性FILE_ATTRIBUTE_TEMPORARY一起使用。当这两个标志一起使用时,你的应用程 序可以创建一个临时文件,读、写,而后关闭它,当文件关闭时系统自动删除它。
FILE_FLAG_BACKUP_SEMANTICS: 在对软件进行备份或恢复操作时,可以指定这个标志。使用这个标志的目的:系统为各个文件设置了被访问的权限,在执行备份或恢复操作时,文件的权限会被修 改,如果不指定这个标志,那么有可能进程不能访问想要访问的文件。
FILE_FLAG_POSIX_SEMANTICS: 该标志告诉系统使用Posix规则访问文件。Posix使
用的文件系统区分文件名的大小写。
FILE_FLAG_OVERLAPPED: 该标志告诉系统你想异步访问一个设备。默认情况下,是以同步文件访问一个设备的。在同步访问设备情况下:当从文件中读取数据时,你的应用程序被挂起,直到 数据读完,一旦数据读完,你的应用程序就又一次获得控制权,继续执行。异步访问设备情况下:当你调用了一个函数从文件中读取数据后,你不必等到I/O操作 结束,你的调用会立即返回,操作系统使用它的线程为你完成读取数据的操作,在读取完数据后,你会得到一个通知。Windows95不支持文件的异步I/O 操作。
下面 说明一下“文件属性标志”:
注意:当你使用CreateFile函数来创建一个文件,并且指定hTemplateFile 为NULL时,下面这些标志无效。
标志 | 说明 |
FILE_ATTRIBUTE_ARCHIVE | 文件是一个存档文件。应 用程序使用该标志,来对文件标记为备份或删除。当CreateFile创建一个新文件时,该标志被自动设置。 |
FILE_ATTRIBUTE_HIDDEN | 文件是隐藏文件。 |
FILE_ATTRIBUTE_NORMAL | 文件没有其它属性集。 |
FILE_ATTRIBUTE_READONLY | 文件是只读的。 |
FILE_ATTRIBUTE_SYSTEM | 文件是操作系统的一部 分,或被操作系统独占使用。 |
FILE_ATTRIBUTE_COMPRESSED | 文件或目录是压缩的。 |
FILE_ATTRIBUTE_OFFLINE | 文件存在,但是它的数据 被移动到离线的存储中。 |
FILE_ATTRIBUTE_TEMPRORARY | 文件中的数据只使用很短 一段时间。文件系统努力使文件的数据保存在RAM中而不是磁盘中,来使访问的时间尽可能短。 |
hTemplateFile:标识一个 打开的文件句柄,或是NULL。如果它标识了一个文件句柄,CreateFile将完全忽略在参数dwFlagsAndAttrs参数中设定的属性标志, 而是使用同hTemplateFile相关联的文件的属性。由hTemplateFile相关联的文件必须使用GENERIC_READ标志打开,如果 CreateFile是打开一个现存的文件而不是创建一个新文件,hTemplateFile参数就被忽略了。
如果CreateFile 成功的创建或打开了一个文件或设备,将返回一个文件或设备的句柄。如果失败将返回INVALID_HANDLE_VALUE。