匿名管道是一种未命名的单向管道,通常在父进程和子进程之间传输数据。匿名管道总是本地的;它们不能用于通过网络进行通信。
1. 概念
CreatePipe
函数创建一个匿名管道并返回两个句柄:读取管道的句柄
和写管道的句柄
,读句柄对管道具有只读访问权限,写句柄对管道具有只写访问权限。
要使用管道进行通信,管道服务器必须将管道句柄传递给另一个进程。通常,这是通过继承实现的;也就是说,该进程允许子进程继承该句柄。
进程还可以使用DuplicateHandle
函数复制管道句柄,并使用某种形式的进程间通信(如DDE或共享内存)将其发送给不相关的进程。
管道服务器可以向管道客户端发送读句柄或写句柄,这取决于客户端是否应该使用匿名管道发送信息或接收信息。
要从管道中读取,请在调用ReadFile
函数时使用管道的读取句柄
。当另一个进程写入管道时,ReadFile调用返回。
如果管道的所有写句柄都已关闭,或者在读取操作完成之前发生错误,ReadFile
调用也可以返回。
要写入管道,请在调用WriteFile
函数时使用管道的写句柄
。WriteFile
调用在将指定的字节数写入管道或发生错误之前不会返回。
如果管道缓冲区已满,并且有更多的字节要写入,则WriteFile不会返回,直到另一个进程从管道中读取,从而使更多的缓冲区空间可用。
管道服务器在调用CreatePipe
时指定管道的缓冲区大小。
匿名管道不支持异步(重叠)读写操作。这意味着你不能在匿名管道中使用ReadFileEx
和WriteFileEx
函数。
此外,ipoverlap
参数当这些函数与匿名管道一起使用时,忽略ReadFile
和WriteFile
的。在关闭所有管道句柄(包括读和写)之前,匿名管道一直存在。
进程可以关闭它的管道通过使用CloseHandle
函数来处理。当进程终止时,所有管道句柄也关闭。
匿名管道使用具有唯一名称的命名管道实现。 因此,通常可以传递句柄到匿名管道到需要命名管道句柄的函数。
1. 管道操作
1.1 简单的管道读写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <Windows.h>
int main() {
std::cout << "Hello, World!" << std::endl;
// 创建管道的信息
SECURITY_ATTRIBUTES attributes = {sizeof(SECURITY_ATTRIBUTES),NULL, TRUE};
// 创建管道
HANDLE pipeReadSite, pipeOutputSite;
if (!CreatePipe(&pipeReadSite, &pipeOutputSite, &attributes, 0)) {
std::cout << "创建管道错误:" << GetLastError() << std::endl;
return -1;
}
// 创建读取线程
const char *content = "Hello World";
if (!WriteFile(pipeOutputSite, content, 12, NULL, NULL)) {
std::cout << "写入管道错误:" << GetLastError() << std::endl;
return -2;
}
char * buffer = static_cast<char *>(malloc(12));
if (!ReadFile(pipeReadSite, buffer, 12, NULL, NULL)) {
std::cout << "读取管道错误:" << GetLastError() << std::endl;
return -3;
}
CloseHandle(pipeOutputSite);
CloseHandle(pipeReadSite);
std::cout << "读取内容:" << buffer << std::endl;
return 0;