[英]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 中调用IoCreateFile
, CreateFileType
作为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(例如NtCreateFile
, NtCreateNamedPipeFile
)默认采用异步模式。 使用同步模式需要一个特定的创建选项,如文档中所述:
FILE_SYNCHRONOUS_IO_ALERT
和FILE_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.