繁体   English   中英

双工模式下名为 pipe 的 Win32 的行为

[英]Behavior of Win32 named pipe in duplex mode

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

文档说“在 pipe 客户端启动之前,pipe 服务器不应执行阻塞读取操作”。 但是在客户端开始从写入线程接收数据之后,正在完成阻塞 ReadFile。

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

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

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

每个文件 object 可以为同步或异步 I/O打开。 (异步 I/O 也称为重叠 I/O。)I/O 模式取决于文件 object 中是否存在FO_SYNCHRONOUS_IO标志。 如果设置了标志,则 I/O 模式是同步的。 否则 I/O 模式是异步的。

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

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


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

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

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

使用任一创建选项,在文件 object 中设置FO_SYNCHRONOUS_IO标志。 FILE_SYNCHRONOUS_IO_ALERT额外设置FO_ALERTABLE_IO标志。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM