Windows内核编程学习笔记“设备I/O”

来源:互联网 发布:教育局网络信息安全 编辑:程序博客网 时间:2024/06/06 17:33

下面介绍一下设备和它们最常见的用途:

设备

最常见的用途

文件

任意数据的持久存储

目录

属性和文件压缩

逻辑磁盘

格式化

物理磁盘

分区表访问

串行口

通过电话线传输数据

并行口

向打印机传送数据

邮件槽

一对多的传输数据,通常通过网络向一台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

套接字

SocketacceptAcceptEx

控制台

CreateConsoleScreenBufferGetStdHandle

所有这些函数标识设备的一个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。

原创粉丝点击