Windows 上的命名管道和 OVERLAPPED
Named pipes and OVERLAPPED on Windows
我即将实施我的第一个 Windows 服务。该服务将连接到蓝牙加密狗,并将一些命令和数据联络到单个客户端进程。
每个进程(客户端、服务器)应至少有两个线程 - 一个阻塞在 Read() 上,另一个处理业务逻辑并偶尔执行 Write()。
检查备选方案后,我决定使用 Named Pipes 进行 IPC,但我无法理解某些设置。具体来说:
- 我希望允许同时读取和写入。我是否需要使用
FILE_FLAG_OVERLAPPED
创建管道,即使我不打算在同一线程上进行读取和写入?
- 如果上面的答案是 'yes',我还需要将
OVERLAPPED
结构传递给 ReadFile()
, WriteFile()
, use GetOverlappedResult()
等吗?如果是这样,这背后的理由是什么?
- 单线程执行非阻塞读写有什么好处?有哪些用例?
编辑
我想澄清一下问题:
- 假设两个线程(读/写)同时访问管道,是否会由于某些内部管道互斥锁而导致一个线程阻塞直到另一个线程完成?
- 设置
FILE_FLAG_OVERLAPPED
会改变这种行为吗?
如果您只是同时使用同一个句柄进行读写,则无需使用 FILE_FLAG_OVERLAPPED。读取或写入管道同一端的其他线程不会导致它阻塞。只有当你想执行异步时才需要它I/O,显然你不需要。
如果您使用 FILE_FLAG_OVERLAPPED,您必须通过 lpOverlapped 参数将有效的 OVERLAPPED 结构传递给 ReadFile 和 WriteFile。如果您不使用此标志并且句柄不可搜索(例如命名管道),那么您必须传递 NULL。
与多线程实现相比,使用单线程异步 I/O 的一大优势是您不必担心并发问题。如果只有一个线程,就不会出现竞争条件和死锁。 (实际上在你的情况下,因为你仍然有两个线程,一个在服务器中,一个在客户端中,如果你真的尝试,你仍然可以有死锁和竞争条件,但是异步 I/O 仍然会让它更容易避开它们。)
要启用对管道的双向访问,您必须指定 PIPE_ACCESS_DUPLEX flag for the dwOpenMode parameter. Asynchronous operation (FILE_FLAG_OVERLAPPED
) 并不是启用双向模式所必需的。
但是,建议对双向管道使用异步 I/O。它允许您在同一个线程上同时发出读取和写入操作(参见 WaitForMultipleObjects)。任一操作都会在 完成 时发出信号。例如,这可以防止冗长的写入操作阻塞潜在的读取操作,并且您将能够及时响应其中任何一个。也许更重要的是,由于您永远不知道数据何时可用,因此您通常希望始终发出读取操作,而不会阻塞您的线程。
CreateNamedPipe 的文档中对此进行了概述:
If [overlapped] mode is enabled, functions performing read, write, and connect operations that may take a significant time to be completed can return immediately. This mode enables the thread that started the operation to perform other operations while the time-consuming operation executes in the background. For example, in overlapped mode, a thread can handle simultaneous input and output (I/O) operations on multiple instances of a pipe or perform simultaneous read and write operations on the same pipe handle. If overlapped mode is not enabled, functions performing read, write, and connect operations on the pipe handle do not return until the operation is finished. The ReadFileEx and WriteFileEx functions can only be used with a pipe handle in overlapped mode. The ReadFile, WriteFile, ConnectNamedPipe, and TransactNamedPipe functions can execute either synchronously or as overlapped operations.
我即将实施我的第一个 Windows 服务。该服务将连接到蓝牙加密狗,并将一些命令和数据联络到单个客户端进程。 每个进程(客户端、服务器)应至少有两个线程 - 一个阻塞在 Read() 上,另一个处理业务逻辑并偶尔执行 Write()。
检查备选方案后,我决定使用 Named Pipes 进行 IPC,但我无法理解某些设置。具体来说:
- 我希望允许同时读取和写入。我是否需要使用
FILE_FLAG_OVERLAPPED
创建管道,即使我不打算在同一线程上进行读取和写入? - 如果上面的答案是 'yes',我还需要将
OVERLAPPED
结构传递给ReadFile()
,WriteFile()
, useGetOverlappedResult()
等吗?如果是这样,这背后的理由是什么? - 单线程执行非阻塞读写有什么好处?有哪些用例?
编辑
我想澄清一下问题:
- 假设两个线程(读/写)同时访问管道,是否会由于某些内部管道互斥锁而导致一个线程阻塞直到另一个线程完成?
- 设置
FILE_FLAG_OVERLAPPED
会改变这种行为吗?
如果您只是同时使用同一个句柄进行读写,则无需使用 FILE_FLAG_OVERLAPPED。读取或写入管道同一端的其他线程不会导致它阻塞。只有当你想执行异步时才需要它I/O,显然你不需要。
如果您使用 FILE_FLAG_OVERLAPPED,您必须通过 lpOverlapped 参数将有效的 OVERLAPPED 结构传递给 ReadFile 和 WriteFile。如果您不使用此标志并且句柄不可搜索(例如命名管道),那么您必须传递 NULL。
与多线程实现相比,使用单线程异步 I/O 的一大优势是您不必担心并发问题。如果只有一个线程,就不会出现竞争条件和死锁。 (实际上在你的情况下,因为你仍然有两个线程,一个在服务器中,一个在客户端中,如果你真的尝试,你仍然可以有死锁和竞争条件,但是异步 I/O 仍然会让它更容易避开它们。)
要启用对管道的双向访问,您必须指定 PIPE_ACCESS_DUPLEX flag for the dwOpenMode parameter. Asynchronous operation (FILE_FLAG_OVERLAPPED
) 并不是启用双向模式所必需的。
但是,建议对双向管道使用异步 I/O。它允许您在同一个线程上同时发出读取和写入操作(参见 WaitForMultipleObjects)。任一操作都会在 完成 时发出信号。例如,这可以防止冗长的写入操作阻塞潜在的读取操作,并且您将能够及时响应其中任何一个。也许更重要的是,由于您永远不知道数据何时可用,因此您通常希望始终发出读取操作,而不会阻塞您的线程。
CreateNamedPipe 的文档中对此进行了概述:
If [overlapped] mode is enabled, functions performing read, write, and connect operations that may take a significant time to be completed can return immediately. This mode enables the thread that started the operation to perform other operations while the time-consuming operation executes in the background. For example, in overlapped mode, a thread can handle simultaneous input and output (I/O) operations on multiple instances of a pipe or perform simultaneous read and write operations on the same pipe handle. If overlapped mode is not enabled, functions performing read, write, and connect operations on the pipe handle do not return until the operation is finished. The ReadFileEx and WriteFileEx functions can only be used with a pipe handle in overlapped mode. The ReadFile, WriteFile, ConnectNamedPipe, and TransactNamedPipe functions can execute either synchronously or as overlapped operations.