You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让两个子进程从同一匿名管道读取同一个写入的数字?

解决方法:让两个子进程读取同一管道写入的数字

匿名管道的核心限制是单向单消费:管道缓冲区中的数据会被第一个成功读取的进程取走,剩余进程无法再获取该数据。你之前尝试的GetStdHandle(STD_INPUT_HANDLE)和cin.peek失败,本质是因为两个子进程共享了同一个管道读端,数据被第一个进程读取后就从缓冲区消失了。

以下是三种可行的解决方案:

1. 创建两个独立的匿名管道

为每个子进程分配一个专属的匿名管道,父进程向每个管道写入相同的数字。这样每个子进程都能从自己的管道读端获取完整数据。

父进程代码示例:

#include <windows.h>
#include <iostream>

int main() {
    SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
    HANDLE hRead1, hWrite1, hRead2, hWrite2;

    // 创建两个独立的管道
    CreatePipe(&hRead1, &hWrite1, &sa, 0);
    CreatePipe(&hRead2, &hWrite2, &sa, 0);

    // 启动子进程1,绑定第一个管道的读端作为标准输入
    STARTUPINFO si1 = { sizeof(STARTUPINFO) };
    si1.hStdInput = hRead1;
    si1.dwFlags = STARTF_USESTDHANDLES;
    PROCESS_INFORMATION pi1;
    CreateProcess(NULL, L"ChildProcess.exe", NULL, NULL, TRUE, 0, NULL, NULL, &si1, &pi1);

    // 启动子进程2,绑定第二个管道的读端作为标准输入
    STARTUPINFO si2 = { sizeof(STARTUPINFO) };
    si2.hStdInput = hRead2;
    si2.dwFlags = STARTF_USESTDHANDLES;
    PROCESS_INFORMATION pi2;
    CreateProcess(NULL, L"ChildProcess.exe", NULL, NULL, TRUE, 0, NULL, NULL, &si2, &pi2);

    // 向两个管道写入相同数字
    int targetNum = 456;
    DWORD bytesWritten;
    WriteFile(hWrite1, &targetNum, sizeof(targetNum), &bytesWritten, NULL);
    WriteFile(hWrite2, &targetNum, sizeof(targetNum), &bytesWritten, NULL);

    // 清理句柄
    CloseHandle(hRead1);
    CloseHandle(hRead2);
    CloseHandle(hWrite1);
    CloseHandle(hWrite2);
    CloseHandle(pi1.hProcess);
    CloseHandle(pi1.hThread);
    CloseHandle(pi2.hProcess);
    CloseHandle(pi2.hThread);

    return 0;
}

子进程代码示例:

#include <windows.h>
#include <iostream>

int main() {
    int num;
    DWORD bytesRead;
    HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
    
    ReadFile(hStdin, &num, sizeof(num), &bytesRead, NULL);
    std::cout << "子进程读取到数字:" << num << std::endl;
    
    return 0;
}

2. 使用命名管道(Named Pipe)

命名管道支持多客户端连接,父进程作为服务器创建管道,两个子进程作为客户端分别连接,父进程向每个连接的客户端写入数据。

父进程代码片段:

#include <windows.h>

int main() {
    // 创建支持多实例的命名管道
    HANDLE hPipe = CreateNamedPipe(
        L"\\\\.\\pipe\\SharedNumberPipe",
        PIPE_ACCESS_OUTBOUND,
        PIPE_TYPE_BYTE | PIPE_WAIT,
        PIPE_UNLIMITED_INSTANCES,
        0, 0,
        5000,
        NULL
    );

    int targetNum = 789;
    DWORD bytesWritten;

    // 等待第一个子进程连接并写入数据
    ConnectNamedPipe(hPipe, NULL);
    WriteFile(hPipe, &targetNum, sizeof(targetNum), &bytesWritten, NULL);
    CloseHandle(hPipe);

    // 重新创建管道实例,等待第二个子进程连接
    hPipe = CreateNamedPipe(
        L"\\\\.\\pipe\\SharedNumberPipe",
        PIPE_ACCESS_OUTBOUND,
        PIPE_TYPE_BYTE | PIPE_WAIT,
        PIPE_UNLIMITED_INSTANCES,
        0, 0,
        5000,
        NULL
    );
    ConnectNamedPipe(hPipe, NULL);
    WriteFile(hPipe, &targetNum, sizeof(targetNum), &bytesWritten, NULL);
    CloseHandle(hPipe);

    return 0;
}

子进程代码片段:

#include <windows.h>
#include <iostream>

int main() {
    HANDLE hPipe = CreateFile(
        L"\\\\.\\pipe\\SharedNumberPipe",
        GENERIC_READ,
        0,
        NULL,
        OPEN_EXISTING,
        0,
        NULL
    );

    int num;
    DWORD bytesRead;
    ReadFile(hPipe, &num, sizeof(num), &bytesRead, NULL);
    std::cout << "子进程读取到数字:" << num << std::endl;

    CloseHandle(hPipe);
    return 0;
}

3. 使用共享内存

父进程创建一块共享内存区域写入数字,两个子进程通过名称打开该共享内存并读取数据,这种方式更适合频繁共享数据的场景。

父进程代码片段:

#include <windows.h>

int main() {
    // 创建共享内存
    HANDLE hFileMap = CreateFileMapping(
        INVALID_HANDLE_VALUE,
        NULL,
        PAGE_READWRITE,
        0,
        sizeof(int),
        L"SharedNumMemory"
    );

    // 映射到进程地址空间并写入数字
    int* pNum = (int*)MapViewOfFile(hFileMap, FILE_MAP_WRITE, 0, 0, sizeof(int));
    *pNum = 101;

    // 等待子进程读取(可根据实际需求调整等待逻辑)
    system("pause");

    // 清理
    UnmapViewOfFile(pNum);
    CloseHandle(hFileMap);

    return 0;
}

子进程代码片段:

#include <windows.h>
#include <iostream>

int main() {
    // 打开共享内存
    HANDLE hFileMap = OpenFileMapping(FILE_MAP_READ, FALSE, L"SharedNumMemory");
    
    // 映射到进程地址空间并读取数字
    int* pNum = (int*)MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, sizeof(int));
    std::cout << "子进程读取到数字:" << *pNum << std::endl;

    // 清理
    UnmapViewOfFile(pNum);
    CloseHandle(hFileMap);

    return 0;
}

内容的提问来源于stack exchange,提问作者Влад Солодов

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 16:16:06