首页 基于Windows使用Pipe通信-匿名管道
文章
取消

基于Windows使用Pipe通信-匿名管道

匿名管道是一种未命名的单向管道,通常在父进程和子进程之间传输数据。匿名管道总是本地的;它们不能用于通过网络进行通信。

1. 概念

CreatePipe函数创建一个匿名管道并返回两个句柄:读取管道的句柄写管道的句柄,读句柄对管道具有只读访问权限,写句柄对管道具有只写访问权限。 要使用管道进行通信,管道服务器必须将管道句柄传递给另一个进程。通常,这是通过继承实现的;也就是说,该进程允许子进程继承该句柄。 进程还可以使用DuplicateHandle函数复制管道句柄,并使用某种形式的进程间通信(如DDE或共享内存)将其发送给不相关的进程。

管道服务器可以向管道客户端发送读句柄或写句柄,这取决于客户端是否应该使用匿名管道发送信息或接收信息。 要从管道中读取,请在调用ReadFile函数时使用管道的读取句柄。当另一个进程写入管道时,ReadFile调用返回。 如果管道的所有写句柄都已关闭,或者在读取操作完成之前发生错误,ReadFile调用也可以返回。

要写入管道,请在调用WriteFile函数时使用管道的写句柄WriteFile调用在将指定的字节数写入管道或发生错误之前不会返回。 如果管道缓冲区已满,并且有更多的字节要写入,则WriteFile不会返回,直到另一个进程从管道中读取,从而使更多的缓冲区空间可用。 管道服务器在调用CreatePipe时指定管道的缓冲区大小。

匿名管道不支持异步(重叠)读写操作。这意味着你不能在匿名管道中使用ReadFileExWriteFileEx函数。 此外,ipoverlap参数当这些函数与匿名管道一起使用时,忽略ReadFileWriteFile的。在关闭所有管道句柄(包括读和写)之前,匿名管道一直存在。 进程可以关闭它的管道通过使用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;

参考

本文由作者按照 CC BY 4.0 进行授权