【问题标题】:Sharing pipe handle across a multi-threaded pipe client跨多线程管道客户端共享管道句柄
【发布时间】:2015-07-22 02:32:09
【问题描述】:

我一直在尝试确定是否可以跨管道客户端的线程共享管道句柄(在 Windows 上)。我最初的想法是我不能,因为除非我同步线程,否则数据可能会在服务器上交错显示,从而导致问题。但是我现在想知道 PIPE_TYPE_MESSAGE 和 PIPE_READMODE_MESSAGE 的管道是否允许我让一个多线程管道客户端共享一个管道句柄。有人对此有明确的答案吗?

我希望在客户端线程之间共享单个管道句柄的原因是为了节省每次我想发送数据时打开管道的成本。我不能轻松地缓存客户端线程的管道句柄,因为我没有创建客户端线程。

我已经包含了来自https://msdn.microsoft.com/en-us/library/windows/desktop/aa365605(v=vs.85).aspx 的sn-p,它描述了管道类型模式。我已经强调了让我想知道消息模式是否会完成我想要做的事情的部分。

...

类型模式

管道的类型模式决定了数据如何写入一个命名的 管道。数据可以通过命名管道作为流传输 字节或消息流。管道服务器指定 调用 CreateNamedPipe 来创建一个实例时的管道类型 命名管道。对于 a 的所有实例,类型模式必须相同 管道。

要创建字节类型管道,请指定 PIPE_TYPE_BYTE 或使用默认值 价值。数据作为字节流写入管道,并且 系统不区分不同写入的字节 写操作。

要创建消息类型管道,请指定 PIPE_TYPE_MESSAGE。 系统 将每个写入操作中写入管道的字节视为 消息单元。系统总是执行写操作 消息类型的管道,就像启用了直写模式一样。

...

谢谢, 尼克

【问题讨论】:

    标签: multithreading client pipe sharing


    【解决方案1】:

    ReadFile 和 WriteFile WinAPI 函数都是线程安全的。与我之前写的不同(对此感到抱歉),这种线程安全并不能保证来自不同线程的并发写入不会被交错。换句话说,不能保证首先开始写入数据的线程会在其他线程获得写入访问权限之前完成。来自 MSDN:

    虽然单扇区写入是原子的,但多扇区写入不能保证是原子的,除非您使用事务(即,创建的句柄是事务句柄;例如,使用 CreateFileTransacted 创建的句柄) .

    这表明可以使用事务操作进行原子写入,但我对这种情况下的事务了解不多。

    为了救赎自己,我将尝试为您的问题提出替代解决方案。您可以在客户端中拥有一个单独的 writer 线程,该线程对管道具有独占写入权限。所有其他线程将它们的消息推送到 FIFO 队列,而写入器线程读取队列并通过管道发送数据。这比锁定整个写入操作要好,因为入队/出队操作要快得多,而且线程不会被长时间阻塞。

    您可以以编写线程可以等待它的方式实现队列,并且仅当队列中有消息时才唤醒。否则,writer 线程将有一个繁忙的循环,这是一个讨厌的解决方案。

    【讨论】:

    • 听起来你在说,因为我的客户将使用的 WriteFile() 是线程安全的,数据不会被交错。看起来操作系统正在同步调用。那是对的吗?因此,如果两个线程使用相同的 FILE 句柄,选择一个相似但略有不同的示例,并且它们各自将一些字节缓冲区写入文件,则无论客户端缓冲区是否大于操作系统或运行时库缓冲区,因此必须将它们自己分成多个写入?
    • 我为我的粗心回答道歉:(。阅读您的评论后,我意识到我错了,我更新了我的答案。请重新检查我的答案。
    • 这又回到了我原来的问题。我假设面向字节的管道可能具有交错的“缓冲区”的潜力。面向消息的管道给我的印象是也许操作系统正在做一些特殊的事情以确保每个写入缓冲区在管道中都是完整的,因此可以处理我概述的多个客户端线程共享相同的场景管柄。
    • 顺便说一句,我用管道类型文档中的 sn-p 更新了我的问题。
    • 我认为将管道类型设置为 PIPE_TYPE_MESSAGE 不会解决问题。如果设置了 BYTE 模式,则操作系统不会区分不同写入操作中写入的数据。因此,您最终可以在读取端从多个写入操作中读取字节。如果 mode 设置为 MESSAGE,那么使用 write 写入的数据就像一个传输包。然后读取操作一次读取一个数据包。但。这并不意味着操作系统将锁定写入操作以防止数据交错,正如我们所讨论的。写入单扇区是原子的,多扇区写入不一定是。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-28
    • 2020-11-18
    • 2010-10-17
    • 2018-07-27
    • 2013-11-12
    • 1970-01-01
    相关资源
    最近更新 更多