进程间通信(IPC)的方法:命名管道

2023-11-16

      使用管道时,一个进程的输出可成为另外一个进程的输入。
      命名管道(Named pipe或FIFO)是一种类似于管道的特殊文件,但在文件系统上有一个名称,它允许以先进先出(FIFO, first in, first out)的方式存储有限数量的数据。它的使用类似于消息传递,其中一个进程发送一条信息,其它进程接收它。数据以FIFO方式以高吞吐速度进入管道。但是,队列一次可以容纳的最大数据大小为16页(pages)或65536字节。它实际上使用了一块内核内存。
      命名管道是在文件系统中作为一个特殊的设备文件而存在。不同祖先的进程之间可以通过命名管道共享数据。当共享命名管道的进程执行完所有的I/O操作以后,命名管道将继续保存在文件系统中,以便以后使用,除非调用unlink。通过命名管道,不相关的进程也能交换数据。一旦已经用mkfifo函数创建了一个FIFO,就可用open打开它。实际上,一般的文件I/O函数(close、read、write、unlink等)都可用于FIFO。
      只要FIFO有空间,write函数就是非阻塞的,但read会阻塞当前线程。
      命名管道总结
      (1).同步(用于单向管道);
      (2).队列大小为16页(page),每页4096字节。只要数据消耗足够快,数据大小就没有限制;
      (3).单个管道的单向通信;
      (4).以线性方式读写;
      (5).自动内存管理。
      注:以上内容主要来自网络整理。
      如果父进程和子进程之间互相发送接收数据,需要两根管道,如以下测试代码:

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <string.h>
#include <error.h>
#include <iostream>
#include <thread>
#include <cctype>

typedef struct message {
    int pid;
    char ch;
} message;

int main(int argc, char **argv)
{
    const char *named_pipe1 = "/tmp/named_pipe1", *named_pipe2 = "/tmp/named_pipe22";
    unlink(named_pipe1); // deletes a name from the file system
    unlink(named_pipe2);

    if (mkfifo(named_pipe1, 0666) < 0 || mkfifo(named_pipe2, 0666) < 0) { // make a FIFO special file(a named pipe), if the file exists, the call will fail
        fprintf(stderr, "fail to mkfifo: %s\n", strerror(errno));
        return -1;
    }

    struct stat buffer1, buffer2;
    if (stat(named_pipe1, &buffer1) != 0 || stat(named_pipe1, &buffer2) != 0) { // retrieve information about the file pointed to by pathname
        fprintf(stderr, "fail to stat: %s\n", strerror(errno));
        return -1;
    }

    pid_t pid = fork();
    if (pid < 0) {
        fprintf(stderr, "fail to fork\n");
        return -1;
    }

    if (pid == 0) { // child process
        auto fd1 = open(named_pipe1, O_RDONLY); // read only
        auto fd2 = open(named_pipe2, O_WRONLY); // write only
        if (fd1 < 0 || fd2 < 0) {
            fprintf(stderr, "fail to open: %d, %s\n", pid, strerror(errno));
            exit(1);
        }

        for (int i = 0; i < 5; ++i) {
            message msg;
            auto ret = read(fd1, &msg, sizeof(msg));
            if (ret < 0) {
                fprintf(stderr, "fail to read: %d, %d %s\n", pid, i, strerror(errno));
                exit(1);
            }

            msg.ch = std::toupper(msg.ch);
            ret = write(fd2, &msg, sizeof(msg));
            if (ret < 0) {
                fprintf(stderr, "fail to write: %d, %d, %s\n", pid, i, strerror(errno));
                exit(1);
            }

            std::this_thread::sleep_for(std::chrono::milliseconds(100));
        }

        close(fd1);
        close(fd2);
        exit(0);
    }

    if (pid > 0) { // parent process
        auto fd1 = open(named_pipe1, O_WRONLY); // write only
        auto fd2 = open(named_pipe2, O_RDONLY); // read only
        if (fd1 < 0 || fd2 < 0) {
            fprintf(stderr, "fail to open: %d, %s\n", pid, strerror(errno));
            exit(1);
        }

        for (unsigned char i = 0; i < 5; ++i) {
            message msg = {pid, 'a'+i};

            auto ret = write(fd1, &msg, sizeof(msg));
            if (ret < 0) {
                fprintf(stderr, "fail to write: %d, %d, %s\n", pid, i, strerror(errno));
                exit(1);
            }

            fprintf(stdout, "src char: %c\n", msg.ch);

            ret = read(fd2, &msg, sizeof(msg));
            if (ret < 0) {
                fprintf(stderr, "fail to read: %d, %d, %s\n", pid, i, strerror(errno));
                exit(1);
            }

            fprintf(stdout, "dst char: %c\n", msg.ch);
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
        }

        close(fd1);
        close(fd2);

        int status;
        auto pid2 = wait(&status); // system call suspends execution of the calling thread until one of its children terminates
        fprintf(stdout, "process ID of the terminated child: %d\n", pid2);
        if (WIFEXITED(status)) { // returns true if the child terminated normally
            fprintf(stdout, "child process ended with: exit(%d)\n", WEXITSTATUS(status));
        }
        if (WIFSIGNALED(status)) { // returns true if the child process was terminated by a signal
            fprintf(stderr, "child process ended with: kill -%d\n", WTERMSIG(status));
        }
    }

    unlink(named_pipe1); // deletes a name from the file system
    unlink(named_pipe2);
    fprintf(stdout, "====== test finish ======\n");
    return 0;
}

      build.sh内容如下:

#! /bin/bash

if [ -d build ]; then
    echo "build directory already exists, it does not need to be created again"
else
    mkdir -p build
fi

cd build
cmake ..
make

rc=$?
if [[ ${rc} != 0 ]];then
    echo "#### ERROR: please check ####"
    exit ${rc}
fi

echo "==== build finish ===="

      CMakeLists.txt内容如下:

cmake_minimum_required(VERSION 3.22)
project(samples_multi_process)

set(CMAKE_BUILD_TYPE Release) # only works under linux
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -O2 -std=c++17")

file(GLOB samples ${PROJECT_SOURCE_DIR}/test_*.cpp)
#message(STATUS "samples: ${samples}")

foreach(sample ${samples})
    string(REGEX MATCH "[^/]+$" name ${sample})
    string(REPLACE ".cpp" "" exec_name ${name})
    #message(STATUS "exec name: ${exec_name}")

    add_executable(${exec_name} ${sample})
endforeach()

      执行结果如下图所示:

      GitHub:https://github.com/fengbingchun/Linux_Code_Test

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

进程间通信(IPC)的方法:命名管道 的相关文章

  • LNMP环境的搭建及PHP网页的发布

    目录 一 安装nginx服务 1 检查网络环境 查看服务器是否可以上网 2 Centos 7 配置阿里云 yum源和安装 EPEL源 1 对默认原文件进行备份 2 配置阿里云yum源 3 安装 EPEL源 4 安装nginx 二 安装my
  • 深度学习图像搜索与识别

    github 搜索 image retrieval 算法大合集 GitHub willard yuan awesome cbir papers Awesome and classical image retrieval papers 模型比
  • 聊一聊基础的CPU寄存器~

    寄存器 CPU内部的存储单元 用于存放从内存读取而来的数据 包括指令 和CPU运算的中间结果 使用寄存器来临时存放数据而不直接操作内存原因如下 CPU的工作原理决定了有些操作只能在CPU内部进行 CPU读写寄存器的速度比读写内存的速度要快很
  • 前端开发实习总结参考范文(合集)

    前端开发实习总结篇一 今天就简单聊聊上面的Struts Spring Hibernate吧 Struts 代表 表示层 Spring代表 业务逻辑层 Hibernate则代表持久层 他们是目前在Java Web编程开发中用得最多的框架 其实
  • 使用hutool读取excel多sheet文件

    首先要使用hutool 可以加载maven
  • 华为手机一直android,华为手机内存不够用?这5个文件夹常清理,可以腾出近10个G内存...

    华为手机的用户量在急剧增加 当然 随时而来的就是许多使用问题 用户反馈最多的就是手机运行问题 手机使用时间一长 就会卡顿 尤其是处理紧急问题时遇到手机怠工 真是没救了 手机卡顿很大程度上是内存问题 平时使用不当造成手机内垃圾信息过多 占用手
  • R语言 第四章 初级绘图(5)课后练习,保存图形,layout函数,绘制组合图形,添加图例

    关注公众号凡花花的小窝 收获更多的考研计算机专业编程相关的资料 添加图例 当图形中包含的数据不止一组时 图例可以帮助你辨别出每个条形 扇形区域或折线各代表哪一类数据 此时 可以使用legend函数来在画布中添加图例 对图形进行相应说明 le
  • nginx root 和alise

    Nginx静态服务配置 详解root和alias指令 简书 jianshu com 静态文件 Nginx以其高性能著称 常用与做前端反向代理服务器 同时nginx也是一个高性能的静态文件服务器 通常都会把应用的静态文件使用nginx处理 配
  • Android下NestedScrolling机制与CoordinatorLayout之源码分析

    1 CoordinatorLayout依赖库 旧版本导入CoordinatorLayout依赖 implementation com android support design 28 0 0 升级Android X后的依赖 impleme
  • STUN和TURN技术浅析

    原文地址 http www h3c com cn MiniSite Technology Circle Net Reptile The Five Home Catalog 201206 747038 97665 0 htm 在现实Inter
  • pytorch中attention的两种实现方式

    class AttnDecoderRNN nn Module def init self hidden size output size dropout p 0 1 max length MAX LENGTH super AttnDecod
  • XMind2TestCase思维导图测试用例转Excel使用方法

    很多测试工程师习惯于用思维导图写测试用例 结构会比较清晰 但是我们通常把思维导图的用例整理至excel或者导入其他工具如禅道 testlink tapd来执行用例或存档 如果再逐条把思维导图转为excel会比较浪费时间 有没有工具可以把思维
  • 数字高程信息30m分辨率SRTM DEM数据下载与拼接(ENVI)

    数据下载 本次下载的数据是SRTMDEM数据 该数据分辨率为30m 可以到官网下载官网地址 http gdex cr usgs gov gdex 官网数据下载需要注册信息 如果部分区域可从网盘下载 网盘地址 链接 https pan bai
  • LeetCode第26题,删除排序数组中的重复项

    LeetCode 高频题 数组篇 26 删除排序数组中的重复项 大家好 我是Panda 今天分享的是LeetCode第26题 删除排序数组中的重复项 力扣题目链接 LeetCode 26 题目描述 给你一个 升序排列 的数组 nums 请你
  • layui后台表格的增删改查

    完整案例 github自己下下来 就是个很一般的ssm项目 但基本功能都有 已部署到云平台 后台管理员地址 暑假时候没做完凑合看吧 账号 17679210786 密码 123456 前后台都是 前台可以自己用手机号注册 别删除原来的内容 先
  • 攻防世界-MISC-练习区-12(功夫再高也怕菜刀)

    题目描述 菜狗决定用菜刀和菜鸡决一死战 这是攻防世界里面训练区的一道流量分析题 用wireshark 打开流量包 然后一级搜索http 二级用分组字节流搜索flag 按CTRL F 并找到no 1367 在Line based text d
  • 移动NB模块M5311(lwm2m协议登录详解)

    身为一个通信专业大三狗 第一次和别人对接项目今天属于我的功能总算是结束了 接下来就是等待联调 心情愉悦 首先NB是什么 这个我就不详细的解释了 我相信大多数人看这篇文章是以实践为开始的 那么多余的就不说了 接下来说具体流程 首先M5311模

随机推荐