C++进程间通信 匿名管道和命名管道

C++进程间通信 匿名管道和命名管道

匿名管道适用于父子进程之间的简单通信,而命名管道则适用于无亲缘关系的进程之间的通信。

1. 匿名管道

匿名管道概述

匿名管道是用于在具有亲缘关系的进程(如父子进程)之间进行单向通信的简单方式。管道创建时包含两个文件描述符:一个用于读(读端),一个用于写(写端)。

匿名管道代码示例

cpp 复制代码
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <cstring>

int main() 
{
    int pipefd[2];  // 用于保存管道文件描述符
    pid_t cpid;
    char buf;

    if (pipe(pipefd) == -1) 
    {  // 创建管道
        perror("pipe");
        exit(EXIT_FAILURE);
    }

    cpid = fork();  // 创建子进程
    if (cpid == -1) 
    {
        perror("fork");
        exit(EXIT_FAILURE);
    }

    if (cpid == 0) 
    {  // 子进程
        close(pipefd[1]);  // 关闭写端
        while (read(pipefd[0], &buf, 1) > 0) 
        {
            write(STDOUT_FILENO, &buf, 1);  // 读取管道并输出到标准输出
        }
        write(STDOUT_FILENO, "\n", 1);
        close(pipefd[0]);  // 关闭读端
        _exit(EXIT_SUCCESS);

    } 
    else 
    {  // 父进程
        close(pipefd[0]);  // 关闭读端
        const char *msg = "Hello from parent process!";
        write(pipefd[1], msg, strlen(msg));  // 写入管道
        close(pipefd[1]);  // 关闭写端
        wait(NULL);  // 等待子进程结束
        exit(EXIT_SUCCESS);
    }
}

代码解释

  1. 管道创建 :pipe(pipefd)创建一个匿名管道,其中pipefd[0]是读端,pipefd[1]是写端。
  2. 进程创建 :fork()创建一个子进程。cpid在子进程中为0,在父进程中为子进程ID。
  3. 子进程 :
    • 关闭写端。
    • 读取管道数据并输出到标准输出。
    • 关闭读端并退出。
  4. 父进程 :
    • 关闭读端。
    • 将消息写入管道。
    • 关闭写端并等待子进程结束。

运行结果

复制代码
Hello from parent process!

2. 命名管道

命名管道概述

命名管道(FIFO)是一种特殊的文件,可以用于无亲缘关系的进程之间进行双向通信。它通过在文件系统中创建一个命名管道文件进行通信。

命名管道代码示例

首先,创建一个命名管道文件:

sh 复制代码
mkfifo /tmp/myfifo

然后,编写两个程序,一个用于写入数据,另一个用于读取数据。

写入数据的程序(writer.cpp)

cpp 复制代码
#include <iostream>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <cstring>

int main() 
{
    const char *fifo = "/tmp/myfifo";
    int fd = open(fifo, O_WRONLY);  // 打开命名管道的写端
    if (fd == -1) 
    {
        perror("open");
        exit(EXIT_FAILURE);
    }
    const char *msg = "Hello from writer process!";
    write(fd, msg, strlen(msg));  // 写入数据到命名管道
    close(fd);  // 关闭管道
    return 0;
}

读取数据的程序(reader.cpp)

cpp 复制代码
#include <iostream>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <cstring>

int main() 
{
    const char *fifo = "/tmp/myfifo";
    char buf[128];
    int fd = open(fifo, O_RDONLY);  // 打开命名管道的读端
    if (fd == -1) 
    {
        perror("open");
        exit(EXIT_FAILURE);
    }
    ssize_t numBytes = read(fd, buf, sizeof(buf));  // 从管道读取数据
    if (numBytes > 0) 
    {
        buf[numBytes] = '\0';
        std::cout << "Received message: " << buf << std::endl;  // 输出读取的数据
    }
    close(fd);  // 关闭管道
    return 0;
}

代码解释

  1. 创建命名管道文件 :通过mkfifo命令在文件系统中创建一个命名管道文件。
  2. 写入数据的程序(writer.cpp) :
    • 打开命名管道的写端。
    • 将消息写入管道。
    • 关闭管道。
  3. 读取数据的程序(reader.cpp) :
    • 打开命名管道的读端。
    • 从管道读取数据。
    • 输出读取的数据。
    • 关闭管道。

运行步骤

  1. 在终端中创建命名管道文件:

    sh 复制代码
    mkfifo /tmp/myfifo
  2. 分别编译writer.cpp和reader.cpp:

    sh 复制代码
    g++ writer.cpp -o writer
    g++ reader.cpp -o reader
  3. 打开两个终端,在第一个终端运行读取程序:

    sh 复制代码
    ./reader
  4. 在第二个终端运行写入程序:

    sh 复制代码
    ./writer

运行结果

第一个终端(运行读取程序)输出:

复制代码
Received message: Hello from writer process!
相关推荐
一晌小贪欢8 分钟前
Python基础:第 09 篇 · while 循环:重复直到不满足
开发语言·c++·python·数据可视化·面向对象·python办公
xiaoye-duck40 分钟前
《C++ 项目:手写大模型接入 SDK》LLMManager架构设计与实现
开发语言·网络·c++·语言模型
say_fall1 小时前
【AI大模型】MCP 模型上下文协议:客户端-服务器架构、JSON-RPC 消息与能力协商、工具发现与调用链路、与函数调用的分工
服务器·人工智能·架构
一条大祥脚1 小时前
CuTe 与 CuTe DSL:从 C++ 模板元编程到 Python DSL 的 GPU 编程演进
开发语言·c++·python·cutlass·cute·cute dsl
·present·1 小时前
CSAPP(lecture 13_02 Linking)
c语言·c++
旖旎夜光2 小时前
【C++ 基础入门】C++ 多态(上):虚函数、重写、override/final 与抽象类
开发语言·c++·笔记·学习
木子欢儿4 小时前
国内 macOS/Linux 安装 rust
linux·运维·服务器·macos·rust
say_fall4 小时前
【Linux网络编程】计算机网络基础:局域网与广域网、OSI七层模型与TCP/IP五层模型、封装解包与MAC/IP地址、端口号与socket编程接口
linux·网络·tcp/ip·计算机网络·信息与通信
青少儿编程课堂4 小时前
蓝桥杯青少组图形化 STEMA 省考(报名倒计时·11/22开考)+ 全国青少年信息素养大赛 2026—2027赛季 + 电子学会图形化考级:校园华容道大闯关
c++·python·算法·bfs·信息学竞赛
迪菲赫尔曼4 小时前
【基础篇 26】第一次在服务器完成训练:准备数据、断线继续、检查成果与备份
运维·服务器·人工智能·机器学习·计算机视觉