Windows中的命名管道,FILE_FLAG_OVERLAPPED和PIPE_NOWAIT

时间:2018-11-10 09:46:52

标签: winapi ipc named-pipes overlap

我在Windows中使用命名管道,并且对FILE_FLAG_OVERLAPPEDPIPE_NOWAIT(它们是在CreateNamedPipe中设置的参数)之间的差异感到困惑,我这样设置参数。

HANDLE hPipe = CreateNamedPipe(
    lpszPipename,             // pipe name 
    PIPE_ACCESS_DUPLEX |      // read/write access 
    FILE_FLAG_OVERLAPPED,     // overlapped mode 
    PIPE_TYPE_MESSAGE |       // message-type pipe 
    PIPE_READMODE_MESSAGE |   // message read mode 
    PIPE_WAIT,                // blocking mode 
    PIPE_UNLIMITED_INSTANCES, // unlimited instances 
    BUFSIZE * sizeof(TCHAR),    // output buffer size 
    BUFSIZE * sizeof(TCHAR),    // input buffer size 
    PIPE_TIMEOUT,             // client time-out 
    NULL);                    // default security attributes

ConnectNamedPipe立即返回,我从ERROR_IO_PENDING得到GetLastError。使用非阻塞等待句柄,connect操作立即返回零,而GetLastError函数返回ERROR_IO_PENDING但是,MSDN会告诉您: 使用非阻塞等待句柄,连接操作立即返回零,而GetLastError函数返回 ERROR_PIPE_LISTENING 因此,nonblocking-waitPIPE_NOWAIT还是FILE_FLAG_OVERLAPPED是什么,非常感谢!

1 个答案:

答案 0 :(得分:3)

PIPE_NOWAIT表示在句柄上启用了非阻塞模式。在此模式下,ReadFileWriteFileConnectNamedPipe总是立即完成

FILE_FLAG_OVERLAPPED表示在句柄上启用了异步模式。如果启用此模式,所有不同步io [1] 操作始终会立即返回

所以FILE_FLAG_OVERLAPPED vs PIPE_NOWAIT-这是立即返回与立即完成

立即

完成(其中包括 return 立即)意味着api返回时io操作已经完成。但是签证反之亦然。如果立即返回操作,这并不意味着操作已经完成。如果操作仍未完成,则ntapi返回代码STATUS_PENDING。在这种情况下,win32 api通常会将上一个错误设置为ERROR_IO_PENDING

在异步句柄模式下io操作完成时,存在三种确定方法。

  1. 将句柄绑定到 IOCP (通过CreateIoCompletionPortBindIoCompletionCallbackCreateThreadpoolIo)。结果是当 io complete-指向OVERLAPPED的指针,我们将其传递给io调用- 将排队回到 IOCP (以防BindIoCompletionCallbackCreateThreadpoolIo系统自己创建 IOCP 并进行监听 并调用我们的注册回调,当指向OVERLAPPED的指针将 被排队到 IOCP
  2. 一些win32 api,例如ReadFileExWriteFileEx以及所有ntapi let 指定将在以下环境中调用的APC完成例程 线程,在io操作完成后开始io操作。 在这种情况下,线程必须执行可警报的等待。这个等待不是 与 IOCP 的绑定句柄兼容(我们不能在 如果文件句柄绑定到 IOCP ,则api调用-系统返回无效 参数错误)
  3. 我们可以创建事件并将其传递给api调用(通过 OVERLAPPED::hEvent)-在这种情况下,此事件将由 io操作开始时的系统,并在io时设置为信号状态 操作完成。在这种情况下,不像前两个选项 io时无其他上下文(指向OVERLAPPED的面指针) 操作完成。通常这是最糟糕的选择。

[1] 存在一些io操作,这些操作始终是同步api。例如GetFileInformationByHandleExSetFileInformationByHandle。但几乎io操作不是同步io。所有这些io操作都将指向OVERLAPPED的指针作为参数。因此,如果api签名中没有指向OVERLAPPED的指针-这是同步api调用。如果存在-通常是异步的(例如,异常CancelIoEx指向重叠的指针与当前操作无关,而与我们要取消的先前io操作有关)。尤其是ReadFileWriteFileDeviceIoControlConnectNamedPipe(内部称为DeviceIoControlFSCTL_PIPE_LISTEN的调用))不是io api同步