《Windows via C/C++》学习笔记 —— 设备I/O之“设备的打开和关闭”

  设备的输入输出,即设备I/O,可以分为“同步”和“异步”两种方式。同步的设备I/O,调用的API函数总是等到设备I/O完成才返回。而异步的设备I/O,可以通过多种方法来实现,但是其根本原理是得到“设备I/O的完成通知”。

 

  本篇主要讨论如何打开和关闭一个设备。注意,这里的设备,不是指像键盘、显示器那种实体。而是一种抽象的概念,指一种与外界通信的对象,可以接受外界的输入,也可以对外界的请求作出响应,称之为设备I/O。这个概念比较抽象,这些设备往往和某个内核对象关联。要打开这些设备,就要创建相关的内核对象。

  这些设备包括文件、目录、逻辑磁盘驱动、物理磁盘驱动、串行端口、并行端口、邮槽、管道、套接字、控制台(如下表):

设备

主要用途 

文件

保存数据

目录

属性和文件压缩设置

逻辑磁盘驱动

磁盘格式化

物理磁盘驱动

访问分区表

串行端口

串行传输数据

并行端口

多位数据同时传输,主要是将数据传输给打印机

邮槽

一对多传输数据,往往适用于一个网络中的一台计算机向其他机器发送数据

命名管道

一对一传输数据,往往适用于一个网络中的一台计算机向其他机器发送数据

匿名管道

一对一传输数据,适用于简单的数据传输,不适用于网络

套接字

以流或数据报的形式发送数据,适用于一个网络中的通信

控制台

一个文字窗口显示缓冲区

 

  要使用这些设备,你首先应该打开这些设备。

  Windows努力隐藏这些设备的差异,所以,很多设备的打开的I/O工作可以通过同一个API函数完成,如下表:

设备

经常用来打开设备的API函数和用法

文件

CreateFile —— 打开设备的函数。

将参数pszName是一个文件路径名。

目录

CreateFile —— 打开设备的函数。

将参数pszName是一个目录名。Windows允许你打开一个目录,通过使用参数FILE_ FLAG_BACKUP_SEMANTICS旗标来呼叫CreateFile函数。打开目录之后,就可以这是目录属性,即文件夹属性,比如正常、隐藏、系统、只读等。

逻辑磁盘驱动

CreateFile —— 打开设备的函数。

将参数pszName设置为字符串“\\.\x:”。 比如要打开C盘,就将其设置为“\\.\C:”。

物理磁盘驱动

CreateFile —— 打开设备的函数。

将参数pszName设置为“\\.\PHYSICALDRIVEx”。比如打开第一个物理硬盘扇区:可以这么调用CreateFile函数:

CreateFile(TEXT("\\.\PHYSICALDRIVE0"), ...);

这样就可以打开一个物理磁盘驱动,并且可以直接访问硬盘分区表。

但是打开物理磁盘驱动是存在潜在危险的,特别是当错误的写入,会造成物理磁盘内容的破坏。

串行端口

CreateFile —— 打开设备的函数。

将参数pszName设置为“COMx”,比如打开COM1串口设备,只要将其设置为“COM1”。

并行端口

CreateFile —— 打开设备的函数。

将参数pszName设置为“LPTx”,比如打开LPT1并行端口,将其设置为“LPT1”。

邮槽(服务器端)

CreateMailslot —— 打开设备的函数。

将参数pszName设置为“\\.\mailslot\mailslotname”,其中,“mailsoltname”是为邮槽取的名字,可以任意,前面的字符串是固定的。

邮槽(客户端)

CreateFile —— 打开设备的函数。

将参数pszName设置为“\\servername\mailslot\mailslotname”,其中,“mailsoltname”是为邮槽取的名字,可以任意,前面的字符串是固定的。

命名管道

(服务器端)

CreateFile —— 打开设备的函数。

将参数pszName设置为“\\.\pipe\pipename”,其中,“pipename”是为命名管道取的名字,可以任意,前面的字符串是固定的。

命名管道

(客户端)

CreateFile —— 打开设备的函数。

将参数pszName设置为“\\servername\pipe\pipename”,其中,“pipename”是为命名管道取的名字,可以任意,前面的字符串是固定的。

匿名管道

CreatePipe —— 打开设备的函数。

无论是客户端还是服务器端都以该函数创建或打开匿名管道。

套接字

socket —— 创建一个套接字描述符accept, or AcceptEx.

控制台

Console

CreateConsoleScreenBuffer,GetStdHandle —— 打开设备的函数

 

  从上表可以发现,很多设备都以CreateFile函数来创建和打开。这个函数以后会讲。

  打开了设备,你得到了一个设备的句柄,你就可以通过该句柄使用其他函数,来对相关设备进行设置。

  比如,现在打开了一个串行端口,然后要设置它的传输波特率:

BOOL SetCommConfig(
   HANDLE       hCommDev,
   LPCOMMCONFIG pCC,
   DWORD        dwSize);

 

  或者,你获得了一个邮槽句柄,可以设置读取数据的等待时间:

BOOL SetMailslotInfo(
   HANDLE hMailslot,
   DWORD  dwReadTimeout);

 

  最后,不要忘记关闭句柄,从而正确地关闭设备:

BOOL CloseHandle(HANDLE hObject);
int closesocket(SOCKET s);   //套接字的关闭

 

  如果你有了一个设备句柄,你可以调查它的设备类型,通过使用GetFileType函数,该函数的返回值表明了它是一个什么类型的设备,可以参考MSDN。

DWORD GetFileType(HANDLE hDevice);

 

  好了,现在让我们来讨论一下CreateFile函数:

HANDLE CreateFile(
   PCTSTR pszName,     
//指明设备类型或一个特定的设备实体
   DWORD dwDesiredAccess,     //访问限制
   DWORD dwShareMode,         //共享方式
   PSECURITY_ATTRIBUTES psa,     //安全描述结构
   DWORD dwCreationDisposition,  //创建和打开方式
   DWORD dwFlagsAndAttributes,   //属性旗标,与缓冲区和文件操作属性有关
   HANDLE hFileTemplate);        //设备模版,一个设备句柄

 

  该函数成功,返回句柄,失败返回INVALID_HANDLE_VALUE(值为-1)。

  如果设置了最后一个参数hFileTemplate,那么就照着这个参数所代表的设备,创建一个属性相同的设备,当然,这个参数所表示的设备要具有“可读”的权限,即有GENERIC_READ访问权限。

  至于该函数的具体用法,可以参看本书或MSDN。

posted on 2008-08-16 22:56  小虎无忧  阅读(3361)  评论(0编辑  收藏  举报

导航