fbpx
维基百科

重叠I/O

重叠I/O(Overlapped I/O)是Windows操作系统异步I/O的实现。自Windows NT引入. 重叠I/O对应于UnixPOSIX异步I/O的API (AIO).

重叠I/O特别适合于大量文件或者socket通信、pipe等场合. Windows 9x不支持重叠I/O.

原理 编辑

线程请求一个重叠操作的Windows API函数返回时,该重叠操作可能已经执行完,也可能未执行完还处于pending状态。发起重叠操作的操作系统API函数返回TRUE,说明该操作已经完成;如果该函数返回FALSE且调用GetLastError函数返回ERROR_IO_PENDING,说明该重叠操作处于pending状态。例如下述情形将同步完成IO操作:[1]

  • NTFS文件系统已压缩文件的读写
  • NTFS文件系统加密文件的读写
  • 写文件时如果要扩展文件长度(除非先用SetFileValidData函数明确修改了文件长度,适合于Windows XP以后版本并且有管理员权限)
  • 数据已经放入了CPU缓存(cache)
  • 操作系统的diskette cache manager面对着大量的文件读写请求,超过了它的线程池的能力,这时新来的文件读写请求将被以同步方式执行。

操作系统在重叠I/O操作执行完毕后,会通知发起重叠I/O请求的线程。有多种可选方式实现:

  • 设备内核对象:重叠I/O函数参数OVERLAPPED中的hEvent为空时,使用WaitForSingleObject在重叠操作的句柄上阻塞,等待其完成。该方法不被推荐,因为如果在同一个设备句柄上同时做多个重叠操作,这将无法区分是哪个同步操作触发句柄被signaled。
  • 事件内核对象:在重叠I/O函数参数OVERLAPPED中的hEvent设置一个事件句柄,重叠I/O函数把这个事件重置为nonsignaled。发起重叠I/O请求的线程可以在这个事件上等待(wait)。重叠I/O操作完成后,操作系统把这个事件置位(signaled)。WaitForSingleObject,GetOverlappedResult或GetOverlappedResultEx也可以在这个事件上阻塞,等待其完成。hEvent对象必须是手动重置;如果使用自动重置,WaitForSingleObject()和 WaitForMultipleObjects()函数永不返回。
  • 使用ReadFileEx(), WriteFileEx()等函数发起重叠I/O请求时,在函数参数给出完成过程(completion routine),重叠I/O执行完毕后操作系统把这些完成过程加入到发起重叠I/O请求的线程的异步过程调用(APC)中,当该线程处于alertable状态时这些APC会被操作系统调度该线程执行。
  • 进程创建I/O完成端口(I/O completion port)对象。使用CreateIoCompletionPort函数把文件句柄与完成端口关联起来。当一个重叠操作请求完成之后,操作系统会检查该操作的设备句柄是否关联了一个完成端口,如果是操作系统就向该完成端口的I/O完成队列中加入一个完成包。若干个线程(即线程池)用GetQueuedCompletionStatus函数在完成端口上等待I/O完成包。这突破了只能在发起重叠操作的线程上异步调用完成过程的限制。
  • 线程池I/O完成对象:创建一个I/O线程池,把一个I/O设备句柄与一个完成函数关联到线程池I/O完成对象。每当执行异步I/O操作之前,调用StartThreadpoolIo函数。当该I/O操作完成时,会自动使用一个线程执行该完成函数。

OVERLAPPED数据结构 编辑

Windows操作系统API的头文件minwinbase.h(包含在windows.h)中,定义了数据结构:

typedef struct _OVERLAPPED { // o   DWORD Internal; //通常被保留。当GetOverlappedResult()的参数bWait为真且字段Internal为STATUS_PENDING,GetOverlappedResult()被阻塞直至重叠操作完成。当GetOverlappedResult()返回False并且GatLastError()返回ERROR_IO_INCOMPLETE时,重叠操作尚未完成。  DWORD InternalHigh; //通常被保留,当GetOverlappedResult()传回False时,为被传输数据的长度。  DWORD Offset; //指定文件的位置,从该位置传送数据,文件位置是相对文件开始处的字节偏移量。调用 ReadFile或WriteFile函数之前调用进程设置这个成员,读写命名管道及通信设备时调用进程忽略这个成员;  DWORD OffsetHigh; //指定开始传送数据的字节偏移量的高位字,读写命名管道及通信设备时调用进程忽略这个成员;  HANDLE hEvent; //发起同步操作的函数应把该事件设为nonsignaled状态;pending操作完成时,操作系统把该事件设为signaled状态  } OVERLAPPED, *LPOVERLAPPED; 

数据结构OVERLAPPED的用途:每个重叠操作使用了自己的OVERLAPPED数据结构对象,可用于区别这些重叠操作。应用程序往往在一块内存的前部用作OVERLAPPED数据结构,紧随其后的是与具体重叠操作有关的输入输出数据。OVERLAPPED和数据缓冲区,只有在重叠操作完成之后,才可以释放;否则会造成进程崩溃。

示例 编辑

按照重叠I/O模式打开一个文件(或其他I/O控制端,如命名管道),注意必须用FILE_FLAG_OVERLAPPED标志:

HANDLE hFile;  hFile = CreateFile(szFileName,  GENERIC_READ,  0,  NULL,  OPEN_EXISTING,  FILE_FLAG_NORMAL | FILE_FLAG_OVERLAPPED,  NULL);  if (hFile == INVALID_HANDLE_VALUE)  ErrorOpeningFile(); 

使用重叠I/O的Windows API函数,如ReadFile(), WriteFile(), WinsockWSASend()WSARecv()需要传递一个结构OVERLAPPED作为函数参数,函数调用后立即返回。由操作系统在后台完成I/O操作。需要注意的是,一个OVERLAPPED结构对象在它绑定的重叠I/O还没有完成前,绝对不能被用户程序修改其值或者重用,也不能释放其所用内存(如果它是函数局部变量那么这个函数不能退出以免局部变量所用的运行栈被卷回(unwinding))。因为操作系统使用OVERLAPPED来区别同一个文件句柄下的可能多个未完成的不同的重叠I/O。同样,重叠I/O完成之前,它的数据缓冲区也决不能被程序读写。

if (!ReadFile(hFile,  pDataBuf,  dwSizeOfBuffer,  &NumberOfBytesRead, //接收I/O操作完成的字节数,对于重叠I/O这个输出值无意义  &osReadOperation ) //OVERLAPPED结构  {//如果函数返回false,表示IO操作没有立即全部执行完  if (GetLastError() != ERROR_IO_PENDING)  {  // Some other error occurred while reading the file.  ErrorReadingFile();  ExitProcess(0);  }  else  // Operation has been queued and  // will complete in the future.  fOverlapped = TRUE;  }  else  // Operation has completed immediately.  // 即使作为重叠I/O提交的请求,仍然有可能被操作系统按照同步方式执行完IO操作,这时不应该再去GetOverlappedResult或WaitForSingleObject  fOverlapped = FALSE;  if (fOverlapped)  {  // Wait for the operation to complete before continuing.  // You could do some background work if you wanted to.  if (GetOverlappedResult( hFile,  &osReadOperation,  &NumberOfBytesTransferred, //接收I/O操作完成的字节数  TRUE))//该参数为true将阻塞该线程等待IO操作完成  ReadHasCompleted(NumberOfBytesTransferred);  else  // Operation has completed, but it failed.  ErrorReadingFile();  }  else  ReadHasCompleted(NumberOfBytesRead); 

参考文献 编辑

  1. ^ MSDN: Asynchronous Disk I/O Appears as Synchronous on Windows. [2016-09-07]. (原始内容于2016-10-19). 

重叠i, 此條目包含過多行話或專業術語, 可能需要簡化或提出進一步解釋, 2016年9月6日, 請在討論頁中發表對於本議題的看法, 並移除或解釋本條目中的行話, overlapped, 是windows操作系统对异步i, o的实现, 自windows, nt引入, 对应于unix的posix异步i, o的api, 特别适合于大量文件或者socket通信, pipe等场合, windows, 9x不支持, 目录, 原理, overlapped数据结构, 示例, 参考文献原理, 编辑线程请求一个重叠操作的windows. 此條目包含過多行話或專業術語 可能需要簡化或提出進一步解釋 2016年9月6日 請在討論頁中發表對於本議題的看法 並移除或解釋本條目中的行話 重叠I O Overlapped I O 是Windows操作系统对异步I O的实现 自Windows NT引入 重叠I O对应于Unix的POSIX异步I O的API AIO 重叠I O特别适合于大量文件或者socket通信 pipe等场合 Windows 9x不支持重叠I O 目录 1 原理 2 OVERLAPPED数据结构 3 示例 4 参考文献原理 编辑线程请求一个重叠操作的Windows API函数返回时 该重叠操作可能已经执行完 也可能未执行完还处于pending状态 发起重叠操作的操作系统API函数返回TRUE 说明该操作已经完成 如果该函数返回FALSE且调用GetLastError函数返回ERROR IO PENDING 说明该重叠操作处于pending状态 例如下述情形将同步完成IO操作 1 NTFS文件系统已压缩文件的读写 NTFS文件系统加密文件的读写 写文件时如果要扩展文件长度 除非先用SetFileValidData函数明确修改了文件长度 适合于Windows XP以后版本并且有管理员权限 数据已经放入了CPU缓存 cache 操作系统的diskette cache manager面对着大量的文件读写请求 超过了它的线程池的能力 这时新来的文件读写请求将被以同步方式执行 操作系统在重叠I O操作执行完毕后 会通知发起重叠I O请求的线程 有多种可选方式实现 设备内核对象 重叠I O函数参数OVERLAPPED中的hEvent为空时 使用WaitForSingleObject在重叠操作的句柄上阻塞 等待其完成 该方法不被推荐 因为如果在同一个设备句柄上同时做多个重叠操作 这将无法区分是哪个同步操作触发句柄被signaled 事件内核对象 在重叠I O函数参数OVERLAPPED中的hEvent设置一个事件句柄 重叠I O函数把这个事件重置为nonsignaled 发起重叠I O请求的线程可以在这个事件上等待 wait 重叠I O操作完成后 操作系统把这个事件置位 signaled WaitForSingleObject GetOverlappedResult或GetOverlappedResultEx也可以在这个事件上阻塞 等待其完成 hEvent对象必须是手动重置 如果使用自动重置 WaitForSingleObject 和 WaitForMultipleObjects 函数永不返回 使用ReadFileEx WriteFileEx 等函数发起重叠I O请求时 在函数参数给出完成过程 completion routine 重叠I O执行完毕后操作系统把这些完成过程加入到发起重叠I O请求的线程的异步过程调用 APC 中 当该线程处于alertable状态时这些APC会被操作系统调度该线程执行 进程创建I O完成端口 I O completion port 对象 使用CreateIoCompletionPort函数把文件句柄与完成端口关联起来 当一个重叠操作请求完成之后 操作系统会检查该操作的设备句柄是否关联了一个完成端口 如果是操作系统就向该完成端口的I O完成队列中加入一个完成包 若干个线程 即线程池 用GetQueuedCompletionStatus函数在完成端口上等待I O完成包 这突破了只能在发起重叠操作的线程上异步调用完成过程的限制 线程池I O完成对象 创建一个I O线程池 把一个I O设备句柄与一个完成函数关联到线程池I O完成对象 每当执行异步I O操作之前 调用StartThreadpoolIo函数 当该I O操作完成时 会自动使用一个线程执行该完成函数 OVERLAPPED数据结构 编辑Windows操作系统API的头文件minwinbase h 包含在windows h 中 定义了数据结构 typedef struct OVERLAPPED o DWORD Internal 通常被保留 当GetOverlappedResult 的参数bWait为真且字段Internal为STATUS PENDING GetOverlappedResult 被阻塞直至重叠操作完成 当GetOverlappedResult 返回False并且GatLastError 返回ERROR IO INCOMPLETE时 重叠操作尚未完成 DWORD InternalHigh 通常被保留 当GetOverlappedResult 传回False时 为被传输数据的长度 DWORD Offset 指定文件的位置 从该位置传送数据 文件位置是相对文件开始处的字节偏移量 调用 ReadFile或WriteFile函数之前调用进程设置这个成员 读写命名管道及通信设备时调用进程忽略这个成员 DWORD OffsetHigh 指定开始传送数据的字节偏移量的高位字 读写命名管道及通信设备时调用进程忽略这个成员 HANDLE hEvent 发起同步操作的函数应把该事件设为nonsignaled状态 pending操作完成时 操作系统把该事件设为signaled状态 OVERLAPPED LPOVERLAPPED 数据结构OVERLAPPED的用途 每个重叠操作使用了自己的OVERLAPPED数据结构对象 可用于区别这些重叠操作 应用程序往往在一块内存的前部用作OVERLAPPED数据结构 紧随其后的是与具体重叠操作有关的输入输出数据 OVERLAPPED和数据缓冲区 只有在重叠操作完成之后 才可以释放 否则会造成进程崩溃 示例 编辑按照重叠I O模式打开一个文件 或其他I O控制端 如命名管道 注意必须用FILE FLAG OVERLAPPED标志 HANDLE hFile hFile CreateFile szFileName GENERIC READ 0 NULL OPEN EXISTING FILE FLAG NORMAL FILE FLAG OVERLAPPED NULL if hFile INVALID HANDLE VALUE ErrorOpeningFile 使用重叠I O的Windows API函数 如ReadFile WriteFile Winsock的WSASend 与WSARecv 需要传递一个结构OVERLAPPED作为函数参数 函数调用后立即返回 由操作系统在后台完成I O操作 需要注意的是 一个OVERLAPPED结构对象在它绑定的重叠I O还没有完成前 绝对不能被用户程序修改其值或者重用 也不能释放其所用内存 如果它是函数局部变量那么这个函数不能退出以免局部变量所用的运行栈被卷回 unwinding 因为操作系统使用OVERLAPPED来区别同一个文件句柄下的可能多个未完成的不同的重叠I O 同样 重叠I O完成之前 它的数据缓冲区也决不能被程序读写 if ReadFile hFile pDataBuf dwSizeOfBuffer amp NumberOfBytesRead 接收I O操作完成的字节数 对于重叠I O这个输出值无意义 amp osReadOperation OVERLAPPED结构 如果函数返回false 表示IO操作没有立即全部执行完 if GetLastError ERROR IO PENDING Some other error occurred while reading the file ErrorReadingFile ExitProcess 0 else Operation has been queued and will complete in the future fOverlapped TRUE else Operation has completed immediately 即使作为重叠I O提交的请求 仍然有可能被操作系统按照同步方式执行完IO操作 这时不应该再去GetOverlappedResult或WaitForSingleObject fOverlapped FALSE if fOverlapped Wait for the operation to complete before continuing You could do some background work if you wanted to if GetOverlappedResult hFile amp osReadOperation amp NumberOfBytesTransferred 接收I O操作完成的字节数 TRUE 该参数为true将阻塞该线程等待IO操作完成 ReadHasCompleted NumberOfBytesTransferred else Operation has completed but it failed ErrorReadingFile else ReadHasCompleted NumberOfBytesRead 参考文献 编辑MSDN Reference ReadFile 页面存档备份 存于互联网档案馆 MSDN Reference WriteFile 页面存档备份 存于互联网档案馆 MSDN Reference OVERLAPPED Data structure 页面存档备份 存于互联网档案馆 I O Completion Port 页面存档备份 存于互联网档案馆 MSDN Asynchronous Disk I O Appears as Synchronous on Windows 2016 09 07 原始内容存档于2016 10 19 取自 https zh wikipedia org w index php title 重叠I O amp oldid 70494021, 维基百科,wiki,书籍,书籍,图书馆,

文章

,阅读,下载,免费,免费下载,mp3,视频,mp4,3gp, jpg,jpeg,gif,png,图片,音乐,歌曲,电影,书籍,游戏,游戏。