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



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

    1. 匿名管道

    匿名管道概述

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

    匿名管道代码示例

    #include 
    #include 
    #include 
    #include 
    #include 
    
    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)是一种特殊的文件,可以用于无亲缘关系的进程之间进行双向通信。它通过在文件系统中创建一个命名管道文件进行通信。

    命名管道代码示例

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

    mkfifo /tmp/myfifo
    

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

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

    #include 
    #include 
    #include 
    #include 
    #include 
    
    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)

    #include 
    #include 
    #include 
    #include 
    #include 
    
    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. 在终端中创建命名管道文件:
      mkfifo /tmp/myfifo
      
    2. 分别编译writer.cppreader.cpp
      g++ writer.cpp -o writer
      g++ reader.cpp -o reader
      
    3. 打开两个终端,在第一个终端运行读取程序:
      ./reader
      
    4. 在第二个终端运行写入程序:
      ./writer
      

    运行结果

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

    Received message: Hello from writer process!
    
  • 相关阅读:
    Yolov5进阶之七目标追踪最新环境搭建
    VUE之旅—day3
    FFmpeg入门详解之16:音频编码原理
    有些段子,外行人根本看不懂,只有程序员看了会狂笑不止
    Powerful number
    Integer类型比较大小【详解】
    华为交换机ssh远程登录配置命令
    11.ROS编程学习:参数管理机制python实现
    运用贪心算法实现卡牌游戏-2023年全国青少年信息素养大赛Python复赛真题精选
    运动耳机推荐:哪些蓝牙耳机最适合运动?
  • 原文地址:https://blog.csdn.net/weixin_44046545/article/details/139307680