现在位置:主页>系统编程> 文章内容

Windows完成端口编程

我要投稿更新日期:2008-07-14 点击:
目录
一 基本概念
二 OVERLAPPED数据结构
三 完成端口的内部机制
创建完成端口
完成端口线程的工作原理
线程间数据传递
线程的安全退出

一 基本概念
       设备---windows操作系统上允许通信的任何东西,比如文件、目录、串行口、并行口、邮件槽、命名管道、无名管道、套接字、控制台、逻辑磁盘、物理磁盘等。绝大多数与设备打交道的函数都是CreateFile/ReadFile/WriteFile等。所以我们不能看到**File函数就只想到文件设备。

       与设备通信有两种方式,同步方式和异步方式。同步方式下,当调用ReadFile函数时,函数会等待系统执行完所要求的工作,然后才返回;异步方式下,ReadFile这类函数会直接返回,系统自己去完成对设备的操作,然后以某种方式通知完成操作。

       重叠I/O----顾名思义,当你调用了某个函数(比如ReadFile)就立刻返回做自己的其他动作的时候,同时系统也在对I/0设备进行你要求的操作,在这段时间内你的程序和系统的内部动作是重叠的,因此有更好的性能。所以,重叠I/O是用于异步方式下使用I/O设备的。

重叠I/O需要使用的一个非常重要的数据结构OVERLAPPED。

       完成端口---是一种WINDOWS内核对象。完成端口用于异步方式的重叠I/0情况下,当然重叠I/O不一定非使用完成端口不可,还有设备内核对象、事件对象、告警I/0等。但是完成端口内部提供了线程池的管理,可以避免反复创建线程的开销,同时可以根据CPU的个数灵活的决定线程个数,而且可以让减少线程调度的次数从而提高性能。





二 OVERLAPPED数据结构
typedef struct _OVERLAPPED {



    ULONG_PTR Internal;//被系统内部赋值,用来表示系统状态



    ULONG_PTR InternalHigh;// 被系统内部赋值,传输的字节数



    union {



        struct {



            DWORD Offset;//和OffsetHigh合成一个64位的整数,用来表示从文件头部的多少字节开始



            DWORD OffsetHigh;//操作,如果不是对文件I/O来操作,则必须设定为0



        };



        PVOID Pointer;



    };



    HANDLE  hEvent;//如果不使用,就务必设为0,否则请赋一个有效的Event句柄



} OVERLAPPED, *LPOVERLAPPED;







下面是异步方式使用ReadFile的一个例子



OVERLAPPED Overlapped;



Overlapped.Offset=345;



Overlapped.OffsetHigh=0;



Overlapped.hEvent=0;



//假定其他参数都已经被初始化



ReadFile(hFile,buffer,sizeof(buffer),&dwNumBytesRead,&Overlapped);



这样就完成了异步方式读文件的操作,然后ReadFile函数返回,由操作系统做自己的事情吧



     



下面介绍几个与OVERLAPPED结构相关的函数



等待重叠I/0操作完成的函数



BOOL GetOverlappedResult (

HANDLE hFile,

LPOVERLAPPED lpOverlapped,//接受返回的重叠I/0结构

LPDWORD lpcbTransfer,//成功传输了多少字节数

BOOL fWait //TRUE只有当操作完成才返回,FALSE直接返回,如果操作没有完成,通过调//用GetLastError ( )函数会返回ERROR_IO_INCOMPLETE



);





宏HasOverlappedIoCompleted可以帮助我们测试重叠I/0操作是否完成,该宏对OVERLAPPED结构的Internal成员进行了测试,查看是否等于STATUS_PENDING值。











三 完成端口的内部机制
创建完成端口

       完成端口是一个内核对象,使用时他总是要和至少一个有效的设备句柄进行关联,完成端口是一个复杂的内核对象,创建它的函数是:

HANDLE CreateIoCompletionPort(



    IN HANDLE FileHandle,



    IN HANDLE ExistingCompletionPort,



    IN ULONG_PTR CompletionKey,



    IN DWORD NumberOfConcurrentThreads



    );







通常创建工作分两步:

第一步,创建一个新的完成端口内核对象,可以使用下面的函数:

       HANDLE CreateNewCompletionPort(DWORD dwNumberOfThreads)



{



          return CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,NULL,dwNumberOfThreads);



};

       

第二步,将刚创建的完成端口和一个有效的设备句柄关联起来,可以使用下面的函数:

       bool AssicoateDeviceWithCompletionPort(HANDLE hCompPort,HANDLE hDevice,DWORD dwCompKey)

上一页12 3 下一页
所有评论

评论列表


我也评论来评论! 点击此处参与本文评论

注意:本站采用匿名评论,请各位网友注意自己的言行