我在Windows中使用命名管道,并且对FILE_FLAG_OVERLAPPED
和PIPE_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-wait
是PIPE_NOWAIT
还是FILE_FLAG_OVERLAPPED
是什么,非常感谢!
答案 0 :(得分:3)
PIPE_NOWAIT
表示在句柄上启用了非阻塞模式。在此模式下,ReadFile
,WriteFile
和ConnectNamedPipe
总是立即完成。
FILE_FLAG_OVERLAPPED
表示在句柄上启用了异步模式。如果启用此模式,所有不同步io [1] 操作始终会立即返回。
所以FILE_FLAG_OVERLAPPED
vs PIPE_NOWAIT
-这是立即返回与立即完成。
完成(其中包括 return 立即)意味着api返回时io操作已经完成。但是签证反之亦然。如果立即返回操作,这并不意味着操作已经完成。如果操作仍未完成,则ntapi返回代码STATUS_PENDING
。在这种情况下,win32 api通常会将上一个错误设置为ERROR_IO_PENDING
。
在异步句柄模式下io操作完成时,存在三种确定方法。
CreateIoCompletionPort
或
BindIoCompletionCallback
或CreateThreadpoolIo
)。结果是当
io complete-指向OVERLAPPED
的指针,我们将其传递给io调用-
将排队回到 IOCP (以防BindIoCompletionCallback
或
CreateThreadpoolIo
系统自己创建 IOCP 并进行监听
并调用我们的注册回调,当指向OVERLAPPED
的指针将
被排队到 IOCP )ReadFileEx
或WriteFileEx
以及所有ntapi let
指定将在以下环境中调用的APC完成例程
线程,在io操作完成后开始io操作。
在这种情况下,线程必须执行可警报的等待。这个等待不是
与 IOCP 的绑定句柄兼容(我们不能在
如果文件句柄绑定到 IOCP ,则api调用-系统返回无效
参数错误)OVERLAPPED::hEvent
)-在这种情况下,此事件将由
io操作开始时的系统,并在io时设置为信号状态
操作完成。在这种情况下,不像前两个选项
io时无其他上下文(指向OVERLAPPED
的面指针)
操作完成。通常这是最糟糕的选择。 [1] 存在一些io操作,这些操作始终是同步api。例如GetFileInformationByHandleEx
,SetFileInformationByHandle
。但几乎io操作不是同步io。所有这些io操作都将指向OVERLAPPED
的指针作为参数。因此,如果api签名中没有指向OVERLAPPED
的指针-这是同步api调用。如果存在-通常是异步的(例如,异常CancelIoEx
指向重叠的指针与当前操作无关,而与我们要取消的先前io操作有关)。尤其是ReadFile
,WriteFile
,DeviceIoControl
,ConnectNamedPipe
(内部称为DeviceIoControl
与FSCTL_PIPE_LISTEN
的调用))不是io api同步>