【问题标题】:Behavior of Win32 named pipe in duplex mode双工模式下 Win32 命名管道的行为
【发布时间】:2020-02-17 08:46:42
【问题描述】:

尝试通过命名管道在单个服务器和单个客户端之间进行读取和写入,而不使用重叠模式。 正在运行两个线程分别进行读取和写入。根据文档,我的理解是,单个连接将同时具有输入和输出缓冲区。所以我应该能够使用单个管道实例并行读写。 编写了一个简单的测试代码,以循环方式从服务器写入客户端。服务器上的读取线程调用 ReadFile 的那一刻,写入线程卡在 WriteFile 上。有人可以解释这种情况下的行为吗?

Documentation 表示“在管道客户端启动之前,管道服务器不应执行阻塞读取操作”。但是阻塞ReadFile是在客户端开始从写线程接收数据之后完成的。

更新 1:我知道 ReadFile 在这里阻止了 WriteFile。但我正在寻找 Microsoft 的文档来解释这种行为。任何链接都将不胜感激。

【问题讨论】:

  • 不确定是否重复,但stackoverflow.com/questions/8069172/… 可能是相关的。
  • @JonathanPotter 谢谢你。实际上,我在发布此内容之前已经阅读了该内容。但是在 msdn 中没有记录在阻塞模式下不允许同时读写。只要有两个不同的缓冲区用于读取和写入,从技术上讲这应该不是问题。但我正在寻找有关此的更多信息。
  • @SolidMercury - CreateNamedPipe 内部调用 ZwCreateNamedPipeFile 和此调用内部调用 IoCreateFileCreateFileTypeNamedPipe。并且对文件的所有操作都是同步执行的——这一切都与FILE_OBJECT有关,不管你调用哪个api来创建它
  • 由于读取和写入缓冲区都获得了,我认为当给定 PIPE_ACCESS_DUPLEX 时,windows 会实现某种异步机制 - 你错了。你有 FILE_OBJECTFO_SYNCHRONOUS_IO 标志。对于此类对象此类文件上的所有 I/O 使用返回的句柄跨所有线程进行序列化。

标签: windows winapi visual-c++


【解决方案1】:

服务器上的读线程调用ReadFile的那一刻,写线程 卡在 WriteFile。

一个管道被两个内核文件对象引用(参见FILE_OBJECT),管道的每一端都有一个。在服务器端,CreateNamedPipe 内部调用本机系统函数NtCreateNamedPipeFile,在内核中调用IoCreateFileCreateFileType 作为CreateFileTypeNamedPipe 传递。

每个文件对象都可以为synchronous or asynchronous I/O 打开。 (异步 I/O 也称为重叠 I/O。)I/O 模式由文件对象中 FO_SYNCHRONOUS_IO 标志的存在决定。如果设置了标志,则 I/O 模式是同步的。否则 I/O 模式是异步的。

对于同步模式,I/O 管理器会序列化文件对象上的所有 I/O 操作。其他线程中对文件的并发 I/O 操作将阻塞(即等待开始),直到当前操作完成。即使查询文件名(也是 I/O 操作)也会阻塞。 (这是 Sysinternals handle.exe 等系统级工具的一个已知问题。如果我们在系统等待同步读取完成时尝试查询管道名称,这可能会阻塞。)

使用多个线程(例如,在一个线程中读取,在另一个线程中写入)在这里根本没有帮助。异步 I/O 在这里是理想的。它更高效(线程更少)并且永远不会死锁。


本机 NT API 和 Windows API 使用不同的选项来指定 I/O 模式。

NT API(例如NtCreateFileNtCreateNamedPipeFile)默认采用异步模式。使用同步模式需要特定的创建选项,如文档中所述:

FILE_SYNCHRONOUS_IO_ALERTFILE_SYNCHRONOUS_IO_NONALERT CreateOptions 标志,顾名思义是互斥的,指定文件上的所有 I/O 操作都将 同步的——只要它们通过引用的文件对象发生 通过返回的 FileHandle。 此类文件上的所有 I/O 都已序列化 使用返回的句柄跨所有线程。

使用任一创建选项,FO_SYNCHRONOUS_IO 标志在文件对象中设置。 FILE_SYNCHRONOUS_IO_ALERT 还设置了 FO_ALERTABLE_IO 标志。

Windows API(例如CreateFileWCreateNamedPipeWCreatePipe)默认采用同步 I/O 模式。为此,它在调用底层 NT API 函数时传递 NT 创建选项FILE_SYNCHRONOUS_IO_NONALERT。 Windows API 标志 FILE_FLAG_OVERLAPPED 覆盖默认请求异步 I/O 模式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-08
    相关资源
    最近更新 更多