`
jfi36jfi
  • 浏览: 17461 次
最近访客 更多访客>>
社区版块
存档分类
最新评论

OVERLAPPED 与 FILE_FLAG_OVERLAPPED

阅读更多

OVERLAPPED 与 FILE_FLAG_OVERLAPPED
2011年03月08日
  OVERLAPPED 与 FILE_FLAG_OVERLAPPED overlapped I/O  Overlapped介绍 利用win32所谓的overlapped I/O特征,可以并行处理I/O操作,并且当任何一个I/O完成时,你的程序会收到一个通告。其它操作系统把这个特征称为nonblockeingI/O或者asynchronous I/O。
  Overlapped I/O是win32的一项技术,你可以要求操作系统为你传送数据,并且在传送完毕时通知你。这项技术使你的程序在I/O进行中仍然能够继续处理事物。Overlapped I/O的基本形式是以ReadFile和WriteFile函数完成的。
  overlapped I/O并行处理I/O操作
  首先以FILE_FLAG_OVERLAPPED告诉Win32说不要使用默认的同步 I/O(在CreataFile函数中设定OVERLAPPED参数)。设立一个OVERLAPPED结构时,设定"I/O请求"的必要参数。接下来,调 用ReadFile()并以OVERLAPPED结构的地址作为最后一个参数。这个时候,理论上,win32会在后台处理I/O操作。你的程序可以继续处 理其他事情。
  OVERLAPPED结构
  typedef   struct   _OVERLAPPED   {   
  DWORD     Internal;     
  DWORD    InternalHigh;     
  DWORD   Offset;     //文件开始读写的偏移位置,该偏移位置从文件头开始算起
  DWORD   OffsetHigh;    //64位的文件偏移位置中较高的32位 
  HANDLE   hEvent;     //event对象,当Overlapped I/O完成时即被激发。
  }   OVERLAPPED,*LPOVERLAPPED;
  OVERLAPPED结构的生命期超过ReadFile()和WriteFile()函数,所以应把这个结构放在一个安全的地方,局部变量不是一个安全的地方,她会很快就过了生存范围。最安全的地方就是heap。
  应用:
  1,  激发的文件handle
  2,  激发的Event对象
  3,  异步过程调用(Asynchronous Precudure Call,APC)
  4,  I/O Completion Ports
  Win32文件操作函数
  Win32之中有三个基本的函数用来执行I/O :
  CreateFile()
  ReadFile();
  WriteFile();
  没有哪一个函数用来关闭文件,只要调用CloseHandle()即可。
  CreateFile()可以用来打开各种资源,包括(但不限制于)
  文件(硬盘、软盘、光盘或者其它)
  串行口和并行口(serial and parallel ports)
  Named pipes
  createFile函数
  HANDLE CreateFile(
  LPCTSTR lpFileName, 
  DWORD dwDesiredAccess, 
  DWORD dwShareMode,  
  LPSECURITY_ATTRIBUTES lpSecurityAttributes, 
  DWORD dwCreationDisposition, 
  DWORD dwFlagsAndAttributes, 
  HANDLE hTemplateFile 
  );
  参数:
  lpFileName :文件名
  dwDesiredAccess:访问模式(写/读),可取值如下:
  GENERIC_READ :允许对设备进行读访问;
  GENERIC_WRITE :允许对设备进行写访问(可组合使用);
  0 :只允许获取与一个设备有关的信息 
  dwShareMode:共享模式,可取值如下:
  FILE_SHARE_READF:允许对文件进行共享读操作;
  LE_SHARE_WRITE: 允许对文件进行共享写操作(可组合使用);
  0:不共享;
  lpSecurityAttributes : 指向一个SECURITY_ATTRIBUTES结构的指针,定义了文件的安全特性
  dwCreationDisposition :如何创建,可取值如下: CREATE_NEW: 创建文件;如文件存在则会出错 
  CREATE_ALWAYS: 创建文件,会改写前一个文件 
  OPEN_EXISTING: 文件必须已经存在。由设备提出要求 
  OPEN_ALWAYS: 如文件不存在则创建它 
  TRUNCATE_EXISTING 将现有文件缩短为零长度 
  dwFlagsAndAttributes :文件属性,一个或多个下述常数 
  FILE_ATTRIBUTE_ARCHIVE 标记归档属性 
  FILE_ATTRIBUTE_COMPRESSED 将文件标记为已压缩,或者标记为文件在目录中的默认压缩方式 
  FILE_ATTRIBUTE_NORMAL: 默认属性 
  FILE_ATTRIBUTE_HIDDEN :隐藏文件或目录 
  FILE_ATTRIBUTE_READONLY: 文件为只读 
  FILE_ATTRIBUTE_SYSTEM :文件为系统文件 
  FILE_FLAG_WRITE_THROUGH: 操作系统不得推迟对文件的写操作 
  FILE_FLAG_OVERLAPPED: 对文件进行重叠(Overlapped)操作 
  FILE_FLAG_NO_BUFFERING: 禁止对文件进行缓冲处理。文件只能写入磁盘卷的扇区块 
  FILE_FLAG_RANDOM_ACCESS: 针对随机访问对文件缓冲进行优化 
  FILE_FLAG_SEQUENTIAL_SCAN :针对连续访问对文件缓冲进行优化 
  FILE_FLAG_DELETE_ON_CLOSE :关闭了上一次打开的句柄后,将文件删除。特别适合临时文件
  也可在Windows NT下组合使用下述常数标记: 
  SECURITY_ANONYMOUS, SECURITY_IDENTIFICATION, SECURITY_IMPERSONATION, SECURITY_DELEGATION, SECURITY_CONTEXT_TRACKING, SECURITY_EFFECTIVE_ONLY 
  hTemplateFile:一个临时文件,将拥有全部的属性拷贝,可以设为0。
  返回值
  如执行成功,则返回文件句柄。
  函数说明:
  INVALID_HANDLE_VALUE表示出错,会设置GetLastError。即使函数成功,但若文件存在,且指定了CREATE_ALWAYS 或 OPEN_ALWAYS,GetLastError也会设为ERROR_ALREADY_EXISTS。
  第6个参数dwFlagsAndAttributes,指定使用传统调用或者Overlapped调用,但不能两个都指定。设定FILE_FLAG_OVERLAPPED值,那对该文件的每一个操作都将是Overlapped操作。
  ReadFile函数
  BOOL ReadFile(
  HANDLE hFile, 
  LPVOID lpBuffer, 
  DWORD nNumberOfBytesToRead, 
  LPDWORD lpNumberOfBytesRead, 
  LPOVERLAPPED lpOverlapped
  );
  参数:
  hFile:文件的句柄
  lpBuffer:用于保存读入数据的一个缓冲区
  nNumberOfBytesToRead:要读入的字符数
  lpNumberOfBytesRead:指向实际读取字节数的指针
  lpOverlapped:如文件打开时指定了FILE_FLAG_OVERLAPPED,那么这个参数必须引用一个OVERLAPPED结构。否则,应将这个参数设为NULL
  返回值:
  调用成功,返回非0
  调用不成功,返回0
  函数说明:
  从文件指针指向的位置开始将数据读出到一个文件中, 且支持同步和异步操作,
  如果文件打开方式没有指明FILE_FLAG_OVERLAPPED的话,当程序调用成功时,它将实际读出文件的字节数保存到lpNumberOfBytesRead指明的地址空间中;
  如果文件打开方式指明FILE_FLAG_OVERLAPPED的话,函数将按照Overlapped结构中指定的位置开始读取数据。
  WriteFile函数
  BOOL WriteFile(
  HANDLE hFile,             
  LPCVOID lpBuffer,             
  DWORD nNumberOfBytesToWrite,  
  LPDWORD lpNumberOfBytesWritten,  
  LPOVERLAPPED lpOverlapped 
  );
  参数:
  hFile:文件的句柄
  lpBuffer:用于保存写入数据的一个缓冲区 nNumberOfBytesToRead:欲写入的字节数
  lpNumberOfBytesRead:指向实际写入字节数的指针
  lpOverlapped:如文件打开时指定了FILE_FLAG_OVERLAPPED,那么这个参数必须引用一个OVERLAPPED结构。否则,应将这个参数设为NULL
  返回值:
  调用成功,返回非0
  调用不成功,返回0
  函数说明:
  从文件指针指向的位置开始将数据写入到一个文件中, 且支持同步和异步操作,
  如果文件打开方式没有指明FILE_FLAG_OVERLAPPED的话,当程序调用成功时,它将实际写入文件的字节数保存到lpNumberOfBytesRead指明的地址空间中;
  如果文件打开方式指明FILE_FLAG_OVERLAPPED的话,函数将按照OVERLAPPED结构中指定的位置开始写入数据。
  Setfilepointer函数
  DWORD SetFilePointer(
  HANDLE hFile,           
  LONG lDistanceToMove,     
  PLONG lpDistanceToMoveHigh, 
  DWORD dwMoveMethod       
  );
  参数: 
  hFile:文件句柄
  lDistanceToMove:移动的字节数低DWORD 
  lpDistanceToMoveHigh:移动的字节数高DWORD,为了支持64位长度的大文件,而           用来指定64字节的高32位,如果文件大小只需要32位则设置为NULL 
  ldwMoveMethod:移动方法,可取值如下:
  FILE_BEGIN 从文件开始处开始移动
  FILE_CURRENT 从文件开始除开始移动
  FILE_END 从文件末尾开始移动
  返回值:
  函数成功,返回文件操作指针的位置;函数失败返回INVALID_SET_FILE_POINTER
  函数说明:
  移动文件指针到相关位置(和文件读写不同,这个函数没有异步版本)
  被激发的File handles
  首先在CreataFile函数中设定FILE_FLAG_OVERLAPPED参数;再设 立一个OVERLAPPED结构时,设定"I/O请求"的必要参数。接下来,调用ReadFile()并以OVERLAPPED结构的地址作为最后一个参 数。这个时候, win32会在后台处理I/O操作。你的程序可以继续处理其他事情。
  如果需等待Overlapped I/O的执行结果,可以调用wait…函数,并设定文件handle为其参数。一旦Overlapped I/O操作完成,文件handle即被激发。
  当你完成操作,请调用GetOverlappedResult函数以确定结果。
  GetOverlappedResult函数
  BOOL GetOverlappedResult(
  HANDLE hFile,                      
  LPOVERLAPPED lpOverlapped,      
  LPDWORD lpNumberOfBytesTransferred,
  BOOL bWait                         
  );
  参数:
  hFile:文件或设备的句柄                      
  lpOverlapped:一个指向OVERLAPPED结构的指针
  lpNumberOfBytesTransferred:真正被传输的字节数
  bWait:是否要等待操作完成,true表示要等待,利用这个特点可以利用它来等待异步文件操作的结束
  返回值:
  如果Overlapped操作成功,则返回ture;否则返回false。
  如果bWait设置为false,而Overlapped还没有完成,GetLastError会返回ERROR_IO_INCOMPLETE.
  实例
  int ReadSomething()
  {
  bool rc;
  HANDLE hFile;
  DWORD numread;
  OVERLAPPED overlap;
  char buf[512];
  hFile = CreateFile("C:\\WINDOWS\\WINFILE.EXE",                        GENERIC_READ,                                    FILE_SHARE_READ|FILE_SHARE_WRITE,                                    NULL,                                    OPEN_EXISTING,                                    FILE_FLAG_OVERLAPPED,                                    NULL);   if (hFile == INVALID_HANDLE_VALUE)   {          return -1;   }   memset(&overlap, 0, sizeof(overlap));   overlap.Offset = 1500;//从文件的第1500位置读取数据
  rc = ReadFile(hFile, buf,    300, &numread,     &overlap);//读取300个字节
  if (rc)
  {
  //the data was read successfully
  }
  else
  {
  if (GetLastError() == ERROR_IO_PENDING)
  {
  WaitForSingleObject(hFile,INFINITE);
  rc = GetOverlappedResult(hFile, &overlap,  &numread,  FALSE);
  }
  else
  {
  //something went wrong
  }
  }
  CloseHandle(hFile);
  return TRUE;
  }
  代码说明:
  虽然你要求一个overlaopped操作,但它并不一定就是overlapped。因为如果操作系统认为它可以快速的取得那份数据,那么文件操作就会在ReadFile()返回之前完成,而ReadFile()将返回true。
  操作系统把这个overlapped操作请求放到队列中等待执行,那么ReadFile() 和WriteFile()都会返回false。你必须调用GetLastError(),如果它传回ERROR_IO_PENDING,那意味着 overlapped操作被放到队列中等待执行。
  被激发的Event对象
  以文件handle作为激发机制,有一个明显的限制,那就是没办法说出到底是哪一个Overlapped操作完成了。调用GetOverlappedResult并不是很好的做法,win32提供了一个比较好的做法。
  OVERLAPPED结构中的最后一个参数是一个Event句柄,如果使用文件handle 作为激发对象,可以设为null;如果设定这个参数为一个Event句柄时,系统会在Overlapped操作完成时,自动将此Event激发。由于每一 个Overlapped都有它自己的OVERLAPPED结构,所以每一个结构都有一个Event对象,用来代表该操作。
  你所使用的Event对象必须是手动重置而非自动重置。因为系统核心可能在你等待该Event对象之前,先激发它,这样你的wait..函数永远都不会返回了。
  使用Event对象搭配Overlapped,你就可以对同一个文件发出多个读写操作,每一个操作有自己的Event对象,然后再调用waitformultipleObject函数来等待其中之一或全部完成。
  异步过程调用(APC)
  使用Overlapped+Event,会产生两个基础问题。一:使用WaitForMultipleObjects函数,你只能够等待最多MAXIMUM_WAIT_OBJECTS个对象;二:你必须不断的根据哪一个handle被激发,而计算如何反映。
  这两个问题可以靠一个所谓的异步过程调用(Asynchronous Procedure Call,APC)解决。使用ReadFileEx()和WriteFileEx()就可以调用这个机制。这两个函数允许你指定一个额外的参数,是一个 callback函数地址。当一个Overlapped I/O 完成时,系统会调用callback函数。这个callback函数被称为I/O Completion routine。
  WriteFileEx函数
  BOOL WriteFileEx(
  HANDLE hFile,
  LPCVOID lpBuffer,
  DWORD nNumberOfBytesToWrite,
  LPOVERLAPPED lpOverlapped,
  LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
  );
  参数:
  hFile:使用FILE_FLAG_OVERLAPPED标识创建的file句柄。
  lpBuffer:指向数据的指针
  nNumberOfBytesToWrite:需要写入的字节数。
  lpOverlapped:OVERLAPPED变量的指针。
  lpCompletionRoutine :函数指针。函数原型为
  VOID CALLBACK FileIOCompletionRoutine(
  DWORD dwErrorCode,
  DWORD dwNumberOfBytesTransfered,
  LPOVERLAPPED lpOverlapped
  );
  返回值:
  函数说明: 将数据写入文件。该函数只能用于异步I/O操作,即overlapped I/O。 注:WriteFile()可以用于同步和异步I/O操作。指定的OVERLAPPED中的hEvent栏位不需要放置一个event handle。可以自由运用。一般将hEvent栏位指向一个结构指针。
  ReadFileEx函数
  BOOL ReadFileEx(
  HANDLE hFile,
  LPVOID lpBuffer,
  DWORD nNumberOfBytesToRead,
  LPOVERLAPPED lpOverlapped,
  LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
  );
  说明:读入数据。参数与上同。
  作用: 为一个特指的通信设备等待一个事件发生,该函数所监控的事件是与该设备句柄相关联的一系列事件。 
  参数: hFile :指向通信设备的一个句柄,该句柄应该是由 CreateFile函数返回的。 
  lpEvtMask :当下表中的任一事件发生后,lpEvtMask会指向下表左端对应的值 ,A pointer to a variable that receives a mask indicating the type of event that occurred. 如果发生错误, pEvtMask 的值为0,否则应该是下表 中的一个值 
  Value Meaning 
  EV_BREAK 0x0040 A break was detected on input.(在输入过程中发生中断) 
  EV_CTS 0x0008 The CTS (clear-to-send) signal changed state.(CTS线上的信号改变状态) 
  EV_DSR 0x0010 The DSR (data-set-ready) signal changed state.(DSR 线上的信号改变状态) 
  EV_ERR 0x0080 A line-status error occurred. Line-status errors are CE_FRAME, CE_OVERRUN, and CE_RXPARITY. 
  EV_RING 0x0100 A ring indicator was detected. 
  EV_RLSD 0x0020 The RLSD (receive-line-signal-detect) signal changed state. 
  EV_RXCHAR 0x0001 A character was received and placed in the input buffer.(输入缓冲区不为空) 
  EV_RXFLAG 0x0002 The event character was received and placed in the input buffer. The event character is specified in the device's DCB structure, which is applied to a serial port by using the SetCommState function. 
  EV_TXEMPTY 0x0004 The last character in the output buffer was sent.(输出缓冲区的数据全部发送出去) 
  lpOverlapped :指向OVERLAPPED结构体的一个指针。如果hFile 是用异步方式打开的(在CreateFile()函数中,第三个参数设置为FILE_FLAG_OVERLAPPED),lpOverlapped 不能指向一个空OVERLAPPED结构体,而是与Readfile()和WreteFile()中的OVERLAPPED参数为同一个参数。如果hFile 是用异步方式打开的,而lpOverlapped 指向一个空的OVERLAPPED结构体,那么函数会错误地报告,等待的操作已经完成(而此时等待的操作可能还没有完成)。 
  如果hFile 是用异步方式打开的,而lpOverlapped 指向一个非空的OVERLAPPED结构体,那么函数WaitCommEvent被默认为异步操作,马上返回。这时,OVERLAPPED结构体必须包含一个由CreateEvent()函数返回的手动重置事件对象的句柄hEven。 
  如果hFile 是用同步方式打开的,那么函数WaitCommEvent不会返回,直到要等待的事件发生。  
  返回值: 如果函数成功,返回非零值,否则返回0。要得到错误信息,可以调用GetLastError 函数。 
  备注: WaitCommEvent函数为指定的通信资源监听一系列的Event,这些Event可以由 SetcommMask 和 GetcommMask 函数来设置和查询。 如果异步操作不能马上完成,那么该函数会返回一个FALSE,同时GetLastError 函数可以截获错误码ERROR_IO_PENDING(#define ERROR_IO_PENDING 997),表示操作转到后台运行。在WaitCommEvent函数返回之前,系统将OVERLAPPED 结构中的hEven句柄设置为无信号状态;当WaitCommEvent函数所等待的任何一个Event发生后,系统将OVERLAPPED 结构中的hEven句柄设置为有信号状态,同时将所发生事件赋给lpEvtMask 。 父进程可以根据lpEvtMask 来做出相应的事件处理,然后也可以调用GetOverlappedResult 函数来判断WaitCommEvent的操作是否成功。 如果WaitCommEvent函数在后台运行的时候,进程企图想通过 SetcommMask 函数来改变当前设备的Event,那么WaitCommEvent函数马上返回,lpEvtMask 指向0。 
分享到:
评论

相关推荐

    api中文版32位的windowsAPI

    FILE_FLAG_OVERLAPPED 允许对文件进行重叠操作 FILE_FLAG_NO_BUFFERING 禁止对文件进行缓冲处理。文件只能写入磁盘卷的扇区块 FILE_FLAG_RANDOM_ACCESS 针对随机访问对文件缓冲进行优化 FILE_FLAG_SEQUENTIAL_...

    delphi 下API函数写串口

    0,nil,OPEN_EXISTING,FILE_FLAG_OVERLAPPED or FILE_ATTRIBUTE_NORMAL,0); if CommHandle = INVALID_HANDLE_VALUE then begin CloseHandle(PostEvent); CloseHandle(ReadOs.hEvent); MessageBox(0,'串口打开...

    FastFileSystem快速文件读写测试

    windows系统内核实验.快速文件系统。 分别用三种方法来实现一个对文件的操作: 无缓冲方式:表示用的标志位是FILE_FLAG_NO_BUFFERING。 缓冲方式:表示用的标志位... 异步方式:表示用的标志位是FILE_FLAG_OVERLAPPED。

    Serial-VC++6

    hCom=CreateFile(name,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,NULL); if(INVALID_HANDLE_VALUE==hCom) { // errLog.Format("create com file faild,port...

    vc 串口通信 RS232

    一个完整的串口通信程序 hComm = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0 , 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,0);

    什么是重叠IO

    为了解决这个问题,windows引进了重 叠io的概念,同样是上面的readfile和writefile,如果在createfile的时候设置了file_flag_overlapped 那么在调用readfile和writefile的时候就可以给他们最后一个参数传递一个...

    C++串口编程(VC)

    对于dwAttrsAndFlags参数及FILE_FLAG_OVERLAPPED标志的由来,可解释如下:Windows文件操作分为同步I/O和重叠I/O(Overlapped I/ O)两种方式,在同步I/O方式中,API会阻塞直到操作完成以后才能返回(在多线程方式中,...

    VC串口编程之深入浅出

    VC串口编程之深入浅出 vc串口编程:深入浅出VC++串口编程之基于 ... //FILE_FLAG_OVERLAPPED:可使用异步的I/O HANDLE hTemplateFile //指向模板文件的句柄,对串口而言该参数必须置为NULL ); .........

    VBA API 32 Serialport MT-SICS

    ' FILE_FLAG_OVERLAPPED. If the file handle was created for overlapped ' input and output (I/O), the application must adjust the position of ' the file pointer after the write operation is finished. ' ...

    MFC与IP多播技术的局域网聊天器网络课程设计

    WSA_FLAG_MULTIPOINT_C_LEAF|WSA_FLAG_MULTIPOINT_D_LEAF| WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) { printf("socket failed with:%d\n",WSAGetLastError()); WSACleanup(); return -1; } //将 sock 绑定到本机...

    gertt点阵图读取器(opengl)

    dwStyle=WS_OVERLAPPEDWINDOW; // Windows Style } AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); // Adjust Window To True Requested Size // Create The Window if (!(hWnd=...

    opengl画图程序附带源代码

    dwStyle=WS_OVERLAPPEDWINDOW; // Windows Style } AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); // Adjust Window To True Requested Size // Create The Window if (!(hWnd=CreateWindowEx( ...

    FlexGraphics_V_1.79_D4-XE10.2_Downloadly.ir

    Added TFlexFileFormat.StreamSupport property (default True), which difines, is it necessary to open file stream or give the file name only. - FIX: If the TCustomProp.Assign method calls when the ...

    ImpREC 1.7c

    - Added checks in PEFile.cpp for invalid executables (Thanks to Snacker!) - Fixed some possible problems on sscanf and ordinals ("%X" with WORD type) v1.5.1 beta2 *PRIVATE* ---------------------- -...

Global site tag (gtag.js) - Google Analytics