简体   繁体   中英

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. 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. 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. 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 ". But the blocking ReadFile is being done after the client starts receiving data from the write thread.

Update 1: I understand that the ReadFile is blocking the WriteFile here. But I am looking for Microsoft's documentation which has the explanation for this behavior. Any links to that would be much appreciated.

The moment the read thread on server calls ReadFile, the write thread gets stuck at WriteFile.

A pipe is referenced by two kernel file objects (see FILE_OBJECT ), one at each end of the pipe. On the server side, CreateNamedPipe internally calls the native system function NtCreateNamedPipeFile , which in the kernel calls IoCreateFile with CreateFileType passed as CreateFileTypeNamedPipe .

Each file object may be opened for either synchronous or asynchronous 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. If the flag is set, the I/O mode is synchronous. Otherwise the I/O mode is asynchronous.

For synchronous mode, the I/O manager serializes all I/O operations on the file object. Concurrent I/O operations on the file in other threads will block (ie wait to begin) until the current operation has completed. Even querying the file name (also an I/O operation) will block. (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.)

Using several threads (eg read in one thread, write in another) does not help here at all. Asynchronous I/O is ideal here. 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.

The NT API (eg NtCreateFile , NtCreateNamedPipeFile ) by default assumes asynchronous mode. 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. All I/O on such a file is serialized across all threads using the returned handle.

With either create option, the FO_SYNCHRONOUS_IO flag is set in the file object. FILE_SYNCHRONOUS_IO_ALERT additionally sets the FO_ALERTABLE_IO flag.

The Windows API (eg CreateFileW , CreateNamedPipeW , CreatePipe ) by default assumes synchronous I/O mode. For this it passes the NT create option FILE_SYNCHRONOUS_IO_NONALERT when calling underlying NT API functions. The Windows API flag FILE_FLAG_OVERLAPPED overrides the default to request asynchronous I/O mode.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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