我即将实现我的第一个Windows服务。该服务将连接到蓝牙适配器,并将一些命令和数据联系到单个客户端进程。 每个进程(客户端,服务器)应至少有两个线程 - 一个阻塞Read(),另一个破解业务逻辑并偶尔执行Write()。
检查备选方案,我决定使用Named Pipes进行IPC,但我无法理解某些设置。具体做法是:
FILE_FLAG_OVERLAPPED
创建管道,即使我不打算在同一个线程上进行读写操作?OVERLAPPED
结构传递给ReadFile()
,WriteFile()
,使用GetOverlappedResult()
等?如果是这样,这背后的理性是什么?修改
我想澄清一下这个问题:
FILE_FLAG_OVERLAPPED
会改变此行为吗?答案 0 :(得分:2)
如果您所做的只是同时使用相同的句柄进行读写,则不需要使用FILE_FLAG_OVERLAPPED。读取或写入管道同一端的其他线程不会导致阻塞。如果你想执行异步I / O,你只需要它,显然你不需要。
如果确实使用了FILE_FLAG_OVERLAPPED,则必须通过lpOverlapped参数将有效的OVERLAPPED结构传递给ReadFile和WriteFile。如果您不使用此标志并且句柄不可搜索(例如,命名管道),则必须传递NULL。
在多线程实现上使用单线程异步I / O的一大优势是您不必担心并发问题。如果您只有一个线程,则不能有竞争条件和死锁。 (实际上在你的情况下,因为你仍然有两个线程,一个在服务器中,一个在客户端,如果你真的尝试,你仍然可能有死锁和竞争条件,但异步I / O仍然可以更容易避免它们。)
答案 1 :(得分:2)
要启用对管道的双向访问,您必须为 dwOpenMode 参数指定PIPE_ACCESS_DUPLEX标志。 Asynchronous operation(FILE_FLAG_OVERLAPPED
)并非严格要求启用双向模式。
但是,对于双向管道,建议使用异步I / O.它允许您在同一个线程上同时发出读取和写入操作(请参阅WaitForMultipleObjects)。在完成时发出任一操作信号。例如,这可以防止冗长的写入操作阻止潜在的读取,并且您能够及时响应任何一个。也许更重要的是,由于您永远不知道数据何时可用,您通常希望始终发出读取操作,而不会阻止您的线程。
CreateNamedPipe的文档中列出了这一点:
如果启用了[重叠]模式,则执行可能需要很长时间才能完成的读取,写入和连接操作的功能可以立即返回。此模式使启动操作的线程能够执行其他操作,同时在后台执行耗时的操作。例如,在重叠模式下,线程可以处理多个管道实例上的同时输入和输出(I / O)操作,或者在同一管道句柄上执行同时读取和写入操作。如果未启用重叠模式,则在操作完成之前,不会返回对管道句柄执行读取,写入和连接操作的函数。 ReadFileEx和WriteFileEx函数只能在重叠模式下与管道句柄一起使用。 ReadFile,WriteFile, ConnectNamedPipe和TransactNamedPipe函数可以同步执行,也可以作为重叠操作执行。