简体   繁体   English

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

[英]Behavior of Win32 named pipe in duplex mode

Trying to read and write through a named pipe between a single server and single client without overlapped mode.尝试通过一个名为 pipe 的单服务器和单客户端之间的读写,没有重叠模式。 Two threads are being run for read and write separately.正在运行两个线程分别进行读取和写入。 My understanding as per the documentation is, a single connection will have both in and out buffer.根据文档,我的理解是,单个连接将同时具有输入和输出缓冲区。 So I should be able to read and write parallely with a single instance of pipe.所以我应该能够使用 pipe 的单个实例并行读写。 Have written a simple test code to write from server to client in a loop.编写了一个简单的测试代码,以循环方式从服务器写入客户端。 The moment the read thread on server calls ReadFile, the write thread gets stuck at WriteFile.服务器上的读取线程调用 ReadFile 的那一刻,写入线程卡在 WriteFile 上。 Could someone explain what is the behavior in this case?有人可以解释这种情况下的行为吗?

Documentation says " The pipe server should not perform a blocking read operation until the pipe client has started ". 文档说“在 pipe 客户端启动之前,pipe 服务器不应执行阻塞读取操作”。 But the blocking ReadFile is being done after the client starts receiving data from the write thread.但是在客户端开始从写入线程接收数据之后,正在完成阻塞 ReadFile。

Update 1: I understand that the ReadFile is blocking the WriteFile here.更新 1:我知道 ReadFile 在这里阻止了 WriteFile。 But I am looking for Microsoft's documentation which has the explanation for this behavior.但我正在寻找 Microsoft 的文档来解释这种行为。 Any links to that would be much appreciated.任何链接将不胜感激。

The moment the read thread on server calls ReadFile, the write thread gets stuck at WriteFile.服务器上的读取线程调用 ReadFile 的那一刻,写入线程卡在 WriteFile 上。

A pipe is referenced by two kernel file objects (see FILE_OBJECT ), one at each end of the pipe.一个 pipe 被两个 kernel 文件对象引用(参见FILE_OBJECT ),在 pipe 的每一端都有一个。 On the server side, CreateNamedPipe internally calls the native system function NtCreateNamedPipeFile , which in the kernel calls IoCreateFile with CreateFileType passed as CreateFileTypeNamedPipe .在服务器端, CreateNamedPipe内部调用本机系统 function NtCreateNamedPipeFile ,在 kernel 中调用IoCreateFileCreateFileType作为CreateFileTypeNamedPipe传递。

Each file object may be opened for either synchronous or asynchronous I/O .每个文件 object 可以为同步或异步 I/O打开。 (Asynchronous I/O is also referred to as overlapped I/O.) The I/O mode is determined by the presence of the FO_SYNCHRONOUS_IO flag in the file object. (异步 I/O 也称为重叠 I/O。)I/O 模式取决于文件 object 中是否存在FO_SYNCHRONOUS_IO标志。 If the flag is set, the I/O mode is synchronous.如果设置了标志,则 I/O 模式是同步的。 Otherwise the I/O mode is asynchronous.否则 I/O 模式是异步的。

For synchronous mode, the I/O manager serializes all I/O operations on the file object.对于同步模式,I/O 管理器序列化文件 object 上的所有 I/O 操作。 Concurrent I/O operations on the file in other threads will block (ie wait to begin) until the current operation has completed.其他线程中对文件的并发 I/O 操作将阻塞(即等待开始),直到当前操作完成。 Even querying the file name (also an I/O operation) will block.即使查询文件名(也是 I/O 操作)也会阻塞。 (This is a known problem for system-level tools such as Sysinternals handle.exe. This can block if we try to query the pipe name while the system is waiting for a synchronous read to complete.) (这是 Sysinternals handle.exe 等系统级工具的一个已知问题。如果我们在系统等待同步读取完成时尝试查询 pipe 名称,这可能会阻塞。)

Using several threads (eg read in one thread, write in another) does not help here at all.使用多个线程(例如在一个线程中读取,在另一个线程中写入)在这里根本没有帮助。 Asynchronous I/O is ideal here.异步 I/O 在这里是理想的。 It's more efficient (fewer threads) and never deadlocks.它更高效(线程更少)并且永远不会死锁。


The native NT API and Windows API use different options to specify the I/O mode.原生 NT API 和 Windows API 使用不同的选项来指定 I/O 模式。

The NT API (eg NtCreateFile , NtCreateNamedPipeFile ) by default assumes asynchronous mode. NT API(例如NtCreateFileNtCreateNamedPipeFile )默认采用异步模式。 Using synchronous mode requires a particular create option, as discussed in the documentation:使用同步模式需要一个特定的创建选项,如文档中所述:

The FILE_SYNCHRONOUS_IO_ALERT and FILE_SYNCHRONOUS_IO_NONALERT CreateOptions flags, which are mutually exclusive as their names suggest, specify that all I/O operations on the file will be synchronous—as long as they occur through the file object referred to by the returned FileHandle. FILE_SYNCHRONOUS_IO_ALERTFILE_SYNCHRONOUS_IO_NONALERT CreateOptions标志,顾名思义是互斥的,指定文件上的所有 I/O 操作将是同步的——只要它们通过返回的 FileHandle 引用的文件 object 发生。 All I/O on such a file is serialized across all threads using the returned handle.使用返回的句柄跨所有线程对此类文件上的所有 I/O 进行序列化。

With either create option, the FO_SYNCHRONOUS_IO flag is set in the file object.使用任一创建选项,在文件 object 中设置FO_SYNCHRONOUS_IO标志。 FILE_SYNCHRONOUS_IO_ALERT additionally sets the FO_ALERTABLE_IO flag. FILE_SYNCHRONOUS_IO_ALERT额外设置FO_ALERTABLE_IO标志。

The Windows API (eg CreateFileW , CreateNamedPipeW , CreatePipe ) by default assumes synchronous I/O mode. Windows API(例如CreateFileW , CreateNamedPipeW , CreatePipe )默认采用同步 I/O 模式。 For this it passes the NT create option FILE_SYNCHRONOUS_IO_NONALERT when calling underlying NT API functions.为此,它在调用底层 NT API 函数时传递 NT 创建选项FILE_SYNCHRONOUS_IO_NONALERT The Windows API flag FILE_FLAG_OVERLAPPED overrides the default to request asynchronous I/O mode. Windows API 标志FILE_FLAG_OVERLAPPED覆盖默认值以请求异步 I/O 模式。

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

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