【问题标题】:Windows Named Pipe ProblemWindows 命名管道问题
【发布时间】:2010-12-18 21:46:49
【问题描述】:

我正在编写一个通过命名管道与用户级应用程序通信的驱动程序。 用户态应用程序通过调用 CreateNamedPipe() 创建命名管道,然后通过调用 IOCTL 将管道名称传递给驱动程序。然后驱动程序通过调用 ZwCreateFile() 打开管道。

然后,用户态应用程序会执行一个循环,从管道读取请求、处理请求并将结果写回管道,即:

while(1) {
ReadFromPipe
ProcessRequest
WriteToPipe
}

驱动基本上是把请求写入管道,然后直接读回答案:

WriteRequestToPipe
ReadAnswerFromPipe

我的问题是,如果 ReadAnswerFromPipe 在应用程序中发生 WriteToPipe 之前发生在驱动程序中,则 ReadAnswerFromPipe 永远不会返回。 所以基本上在做

WriteRequestToPipe
Sleep(10 seconds)
ReadAnswerFromPipe

解决问题。

为什么我会看到这个?

澄清:我正在使用两个不同的单向管道,尽管应用程序最终成功调用了 WriteToPipe,但 ReadAnswerFromPipe 调用永远不会返回...

【问题讨论】:

  • 能否附上相关代码sn-ps?

标签: c windows driver named-pipes drivers


【解决方案1】:

由于命名管道在任何给定时间都支持单向通信,因此您必须使用 2 个管道(如前所述)进行真正的异步访问,或者同步访问单个管道(如对讲机)。 semaphore object 应该可以很好地解决这个问题。如果您只是将 CreateSemaphore() 的最大计数参数设置为 1,它将充当二进制信号量。然后,您可以在客户端和服务器上的 while(true) 消息循环内的该信号量上 ZwWaitForSingleObject(),您将获得同步访问。

编辑:刚刚记得您正在编写一个驱动程序作为它的服务器组件,因此您将需要内核特定的函数和结构体,即驱动程序端的KSEMAPHORE 结构体。 p>

【讨论】:

  • 如果在创建时指定PIPE_ACCESS_DUPLEX,命名管道是双向的!我自己也用。
【解决方案2】:

管道通常被视为单向通信通道。

我相信对您来说最简单的解决方案是创建两个管道:一个用于应用程序→驱动程序消息,一个用于驱动程序→应用程序消息。

【讨论】:

  • 那没有回答我的问题
【解决方案3】:

不知道您正在为哪个版本的 Windows 编写,或者您所处的开发环境,我不确定这是否一定会有所帮助,但它可能会有所帮助。

如果您保证每次从驱动程序发送请求时都能从用户应用中获得响应,您可以考虑使用 API 函数 TransactNamedPipe()(请参阅 this page in the MSDN 以获取完整的使用文档)。

它专门用于发送/接收,并会等到响应返回后再返回。

或者,您可以在“重叠”模式下使用此函数,在这种情况下,它将立即返回,然后您等待一个事件 - 您必须在原始调用中作为“TransactionOverlapped”结构的一部分传入- 知道您已收到您的答复。

【讨论】:

  • 我已经尝试在驱动程序中异步执行它,在文件句柄上调用 ZwWaitForSingleObject 但我仍然遇到同样的问题(ZwWaitForSingleObject 永远不会返回......)无论如何谢谢
【解决方案4】:

最好使用 IOCTL 与用户空间进行通信。为什么需要管道?

【讨论】:

    【解决方案5】:

    ehemient 是正确的。您可以坚持使用单个管道,但是您必须在两端之间同步读取和写入。添加的睡眠似乎对您有用,因为它允许在读取答案之前读取请求 - 但这很容易出错,因为一端的延迟可能会导致错误。

    【讨论】:

    • 那没有回答我的问题
    猜你喜欢
    • 1970-01-01
    • 2016-03-30
    • 1970-01-01
    • 2017-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-31
    • 1970-01-01
    相关资源
    最近更新 更多