简体   繁体   English

Windows命名管道问题

[英]Windows Named Pipe Problem

I'm writing a driver that communicates with a userland application through a named pipe. 我正在编写一个通过命名管道与用户态应用程序通信的驱动程序。 The userland application creates the named pipe by calling CreateNamedPipe() and then passes the pipe name to the driver by invoking an IOCTL. userland应用程序通过调用CreateNamedPipe()创建命名管道,然后通过调用IOCTL将管道名称传递给驱动程序。 The driver then opens the pipe by calling ZwCreateFile(). 然后驱动程序通过调用ZwCreateFile()打开管道。

The userland application then hits a loop that reads requests from the pipe, processes the requests and writes back the result to the pipe ie: 然后userland应用程序命中一个循环,该循环读取来自管道的请求,处理请求并将结果写回管道,即:

while(1) {
ReadFromPipe
ProcessRequest
WriteToPipe
}

The driver basically writes requests to the pipe and then directly reads back the answer: 驱动程序基本上将请求写入管道,然后直接读回答案:

WriteRequestToPipe
ReadAnswerFromPipe

My problem is that if the ReadAnswerFromPipe happens in the driver before the WriteToPipe happens in the application, ReadAnswerFromPipe never returns. 我的问题是,如果在应用程序中发生WriteToPipe之前在驱动程序中发生ReadAnswerFromPipe,则ReadAnswerFromPipe永远不会返回。 So basically doing 所以基本上做

WriteRequestToPipe
Sleep(10 seconds)
ReadAnswerFromPipe

fixes the problem. 解决了这个问题。

Why am I seeing this? 我为什么看到这个?

Clarification: I'm using two different unidirectional pipes and the ReadAnswerFromPipe call is never returning although the application eventually successfully calls WriteToPipe... 澄清:我使用两个不同的单向管道,尽管应用程序最终成功调用WriteToPipe,但ReadAnswerFromPipe调用永远不会返回...

Since named pipes support one-way communication at any given time, you will have to either use 2 pipes (as already suggested) for true asynchronous acces, or synchronize access to a single pipe (like a walkie-talkie). 由于命名管道在任何给定时间都支持单向通信,因此您必须使用2个管道(如已建议的)进行真正的异步访问,或者同步访问单个管道(如步话机)。 A semaphore object should work well for that. 信号量对象应该可以很好地工作。 If you just set the Maximum Count parameter of CreateSemaphore() to 1 it will act as a binary semaphore. 如果只将CreateSemaphore()的Maximum Count参数设置为1,它将充当二进制信号量。 You can then ZwWaitForSingleObject() on that semaphore inside your while(true) message loop on both your client and server and you will have synchronized access. 然后,您可以在客户端和服务器上的while(true)消息循环内的该信号量上使用ZwWaitForSingleObject() ,并且您将具有同步访问权限。

Edit: Just remembered you are writing a driver as the server component of this, so you will need the kernel-specific functions and structs, the KSEMAPHORE struct on the driver side. 编辑:记得您正在编写驱动程序作为此服务器组件,因此您将需要特定于内核的函数和结构,驱动程序端的KSEMAPHORE结构。

Pipes are generally taken to be uni-directional communications channels. 管道通常被视为单向通信信道。

I believe that the easiest solution for you would be to create two pipes: one for application→driver messages, and one for driver→application messages. 我相信最简单的解决方案是创建两个管道:一个用于应用程序→驱动程序消息,一个用于驱动程序→应用程序消息。

Not knowing what version of Windows you're writing for, or what development environment you're in, I'm not sure this will necessarily help, but it might. 不知道你正在编写什么版本的Windows,或者你所处的开发环境,我不确定这一定会有所帮助,但它可能会有所帮助。

If you're guaranteed to get a response from your user app every time you send the request from your driver, you might consider using the API function TransactNamedPipe() (see this page in the MSDN for full usage documentation). 如果您确保每次从驱动程序发送请求时都从用户应用程序获得响应,则可以考虑使用API​​函数TransactNamedPipe()(有关完整使用文档,请参阅MSDN中的此页面 )。

It is specifically meant to do a send/receive and will wait until a response comes back before returning. 它专门用于执行发送/接收,并将等到响应返回之前返回。

Alternatively, you can use this function in 'overlapped' mode, in which case it will return immediately, after which you wait on an event - that you have to pass in as part of a 'TransactionOverlapped' structure in the original call - to know that you've received your answer. 或者,你可以在'重叠'模式下使用这个功能,在这种情况下它会立即返回,之后你等待一个事件 - 你必须作为原始调用中'TransactionOverlapped'结构的一部分传入 - 知道你收到了答案。

It is better to use IOCTL for communication with userland. 最好使用IOCTL与userland进行通信。 Why do you need pipes? 你为什么需要管道?

ephemient is correct. ephemient是正确的。 You could stick with a single pipe but then you'd have to synchronise reads and writes between the two ends. 您可以坚持使用单个管道,但是您必须在两端之间同步读取和写入。 The added sleep appears to be working for you as it is allowing the request to be read before the answer is read - but this is error prone as a delay on one end could cause errors. 添加的睡眠似乎对您有用,因为它允许在读取答案之前读取请求 - 但这很容易出错,因为一端的延迟可能导致错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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