进程通信——管道

什么是进程通信?

进程通信是实现进程间传递数据信息的机制。要实现数据信息传递就要进程间共享资源——内存空间。那么是哪块内存空间呢?进程间是相互独立的,一个进程不可能访问其他进程的内存空间,那么这块空间只能由操作系统提供。进程通信的方式有多种,管道就是一种。

管道是一种最简单的通信机制,管道分为匿名管道和命名管道。匿名管道通常用于父子进程之间。命名管道可实现任意两个进程通信。

匿名管道

原理

父进程打开管道文件流(读写两个流),分配描述符到文件描述符表。两个新的文件描述符分别指向管道的读端和写端。父进程创建子进程时,子进程的文件描述符表和父进程指向相同。父子进程指向的文件流都是共享的。

父子进程通信时,如果子进程写,父进程读,子进程关闭pipe_r,父进程关闭pipe_w;如果子进程读,父进程写,子进程关闭pipe_w,父进程关闭pipe_r。

使用样例

pipefd是一个输出型参数,pipefd[0] 表示的是读端的文件描述符,pipefd[1]表示的是写端文件描述符

创建管道->创建子进程->子进程关闭读端,写;父进程关闭写端,读->父进程等待子进程 

#include <iostream>
#include <unistd.h>
#include <cstdlib>
#include <sys/types.h>
#include <sys/wait.h>

using namespace std;
void Write(int fd)
{
    char buffer[1024] = {0};
    pid_t id = getpid();
    int n = 0;
    string s = "I am child";
    while(1)
    {
        snprintf(buffer,sizeof(buffer),"%s-%d-%d",s.c_str(),id,n);
        n++;
        write(fd,buffer,sizeof(buffer));
        sleep(1);
        if(n == 5) break;
    }
}

void Read(int fd)
{
    char buffer[1024] = {0};
    while(1)
    {
        ssize_t s = read(fd,buffer,sizeof(buffer));
        if(s > 0)
        {
            cout << buffer << endl;
        }
        else if(s == 0)
        {
            cout << "read ending" << endl;
            break;
        }
        else{
            cout << "read fail" << endl;
        }
    }
}


int main()
{
    int pipefd[2] = {0};
    pipe(pipefd);
    pid_t id = fork();
    if(id < 0) return -1;
    if(id == 0)
    {
        //child
        close(pipefd[0]);//关闭读端
        Write(pipefd[1]);

        //close(pipefd[1]);
        exit(0);
    }
    //father
    close(pipefd[1]);//关闭写端
    Read(pipefd[0]);
    
    pid_t ret = waitpid(id,nullptr,0);
    if(ret==id) cout << "wait success" << endl;
    else cout << "wait fail" << endl;
    //close(pipefd[0]);
    return 0;
}

命名管道

命名管道原理和匿名管道一样,区别就是命名管道会创建一个管道文件,两个进程分别对文件读写就可以了

使用样例

创建管道文件

 

销毁管道文件

 

 

//communicate.hpp 创建销毁管道进行封装
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>

class Init
{
public:
    Init()
    {
        int n = mkfifo("./myfifo", 0777);
        if (n == -1)
        {
            perror("fifo:");
            exit(-1);
        }
    }

    ~Init()
    {
        int n = unlink("./myfifo");
        if(n == -1)
        {
            perror("unlink:");
            exit(-1);
        }
    }
};

//sever.cpp 服务器负责维护管道,读客户端数据
#include "communicate.hpp"
using namespace std;
int main()
{
    // 创建管道
    Init init;
    // 打开管道
    int fd = open("./myfifo", O_RDONLY);
    if (fd == -1)
    {
        cout << strerror(errno) << endl;
        return -1;
    }

    // 开始通信
    while (1)
    {
        char buffer[1024] = {0};
        ssize_t ret = read(fd, buffer, sizeof(buffer));
        if (ret > 0)
        {
           cout << "sever get inf:" << buffer << endl;
        }
        else if (ret == 0)
        {
            cout << "client quit, sever quit too" << endl;
            break;
        }
        else
            break;
    }

    // 结束通信
    close(fd);
}

//client.cpp 客户端负责向服务器写数据
#include "communicate.hpp"

using namespace std;

int main()
{
    //打开管道
    int fd = open("./myfifo", O_WRONLY);
    if(fd < 0)
    {
        cout << strerror(errno) << endl;
        return -1;
    }

    //进行通信
   while(1)
   {
        string ord;
        cout << "Input:";
        getline(cin, ord);
        write(fd, ord.c_str(), ord.size());
   }

   close(fd);
   return 0;
}

管道特征

  • 只有具有血缘关系的进程可以匿名管道通信

因为只有血缘关系的进程的可以指向同一个匿名管道,达成资源(内存空间)共享,这是通信的前提

  • 管道只能单向通信
  • 通信的进程会进行协同,同步与互斥,为了保证管道文件数据的安全

例如上面的样例:写端每写一次都会等待1s,写端没有写完时,读端会等待进行协同

  • 管道是面向字节流的

管道以字节为单位传输数据,而不是以消息或记录为单位。这意味着数据在传输过程中没有特定的结构或边界,发送方可以连续写入任意数量的字节,接收方则按照字节顺序读取数据。

  • 管道是基于文件的,文件的生命周期是随进程的

管道会随着进程结束而关闭,例如基础IO流并不需要用户手动关闭。在上面的例子中,子进程是写端,没有close(pipdf[1])也不会有错误,同样的父进程是读端,没有close(pipdf[0])不会有错误,因为进程结束这个管道流会自动关闭。

管道的4种情况

  1. 读写端正常,管道为空,读端就要阻塞
  2. 读写端正常,管道为满,写端就要阻塞
  3. 写端关闭,读端正常,读端读到0,表明读到了管道文件的结尾
  4. 读端关闭,写端正常,写端会被异常终止

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/674451.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

私有化部署的无忧企业文档,助力企业实现文档权限的精细化管理

在当今数字化快速发展的时代&#xff0c;企业文档管理已成为企业运营中不可或缺的一部分。文档的安全性和访问权限的精确控制对于企业的信息保护至关重要。在无忧企业文档管理系统中&#xff0c;不仅具备强大的内容管理能力&#xff0c;更在权限管理上做到了细致入微。下面我对…

完全背包(类买卖股票问题)

题目传送门——纪念品 题解&#xff1a;这题我一开始以为是简答的那个买卖股票问题&#xff0c;但是做了之后发现并没有那么简单&#xff0c;但是经过思考时候&#xff0c;我发现其和完全背包类问题差不多&#xff0c;怎么说呢&#xff0c;我们首先用p[i][j]去统计每天每种物品…

手写最小的 Agent 系统 — Tiny Agent

调研Agent核心思想&#xff0c;主要有metagpt、React、Reflexion、Toolformer、Swiftsage、Creator等等。Tiny Agent 实现&#xff0c;主要包括 构造大模型、构造工具、构造Agent、运行Agent等步骤。 Agent 核心思想 1. MetaGPT METAGPT: META PROGRAMMING FOR A MULTI-AGEN…

bugku 隐写

说明&#xff1a; 隐写&#xff0c;通过改变图片的大小&#xff0c;即修改了高或者宽&#xff0c;达到隐写flag&#xff0c;要求修改会图片的真实大小找到flag。 1、打开图片 2、使用010editor工具打开图片 通过最下面黄底字的错误提示&#xff0c;表示CRC不匹配&#xff0c;…

如何创建一个Angular项目(超简单)

1、安装Node.js&#xff08;官网Node.js下载&#xff09; 2、运行node -v和npm -v两条命令&#xff08;检验是否下载成功Node.js&#xff09; 3、npm i -g cnpm --registryhttps://registry.npmmirror.com&#xff08;用npm安装cnpm&#xff0c;将镜像源设置为国内镜像源&…

python办公自动化——(三)替换PPT文档中图形数据-折线图

数据替换前 数据替换后 代码实现 # 单折线 pathE:\\13 python 下侧双x轴折线图\\ prs Presentation(path双x轴测试-01.pptx) data_timepd.read_excel(path"数据.xlsx",sheet_name单折线)ppt_9prs.slides…

汽车识别项目

窗口设计 这里的代码放在py文件最前面或者最后面都无所谓 # 创建主窗口 window tk.Tk() window.title("图像目标检测系统") window.geometry(1000x650) # 设置窗口大小# 创建背景画布并使用grid布局管理器 canvas_background tk.Canvas(window, width1000, height…

BugKu 哎,就是玩

说明&#xff1a;通过图片隐写找到迷宫压缩包解码密码&#xff0c;然后通过MG游戏得到井字棋游戏解压密码&#xff0c;最后通过完成井字棋得到flag. 打开实验包&#xff0c;解压后可以看到两个文件。 首先要通过TKR.png找到迷宫.zip的解压密码。 打开图片&#xff0c;发现图片…

二叉树创建和遍历

个人主页 &#xff1a;敲上瘾-CSDN博客二叉树介绍&#xff1a;二叉树(详解)-CSDN博客 目录 一、二叉树的创建 二、二叉树的遍历 1.前序遍历 2.中序遍历 3.后序遍历 4.层序遍历 三、相关计算 1.总节点个数计算 2.叶子节点个数计算 3.深度计算 一、二叉树的创建 关于…

24.6.2(动态开点线段树)

星期一&#xff1a; cf edu round 36 E cf传送门 题意&#xff1a;1到n天初始全为工作日&#xff0c;有两种操作&#xff0c;将 l-r 区间变为 工作日/休息日&#xff0c;每次操作后询问剩余总工作日有多少 思路&…

AIGC绘画设计基础——“这是我学一天AI设计后的作品,效率真的高。”

不少小伙伴都在用Midjourney生成图像作品&#xff0c;但对于完整的设计流程却不太熟悉。今天数艺君就跟大家分享一个干货内容&#xff1a;使用Midjourney设计一个动物IP形象&#xff01; 包含整个项目流程&#xff1a;从项目背景到需求分析&#xff0c;再到出图思路和提示词设计…

Paper Survey——3DGS-SLAM

之前博客对多个3DGS SLAM的工作进行了复现及代码解读 学习笔记之——3DGS-SLAM系列代码解读_gs slam-CSDN博客文章浏览阅读1.9k次&#xff0c;点赞15次&#xff0c;收藏45次。最近对一系列基于3D Gaussian Splatting&#xff08;3DGS&#xff09;SLAM的工作的源码进行了测试与…

竞赛 基于视觉的身份证识别系统

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于机器视觉的身份证识别系统 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f9ff; 更多资料, 项目分享&#xff1a; https://gitee.com/dancheng-sen…

GNeRF论文理解

文章目录 主要解决什么问题&#xff1f;结构设计以及为什么有效果&#xff1f;个人想法。 主要解决什么问题&#xff1f; 本文主要想要解决的问题是 如何使用uncalibrated的照片来进行Nerf重建。虽然说现在已经有了一些方式可以对相机位姿进行估计和优化&#xff0c;但是他们限…

速通systemverilog

这里写目录标题 一、systemverilog的大部分新语法logicalways_combunique_casepriority casealways_fftypedefstructenumunioninterface 二、实现流水灯三、全加器以及仿真 一、systemverilog的大部分新语法 logic always_comb unique_case priority case case中常量和变量互…

SAP-FICO总账科目案例

1、资产科目 2、负债科目

学习笔记之——2D Gaussian Splatting(2DGS)

3DGS在辐射场重建中取得了巨大的成就&#xff0c;实现高质量的新视图合成和快速渲染。最近新出了3DGS的升级版本&#xff0c;2DGS。写下本博文记录本人学习及测试2DGS的过程&#xff0c;本博文仅为本人学习记录用~ Project WebsiteGithub CodeOriginal paper 目录 原理解读 …

Vue3项目炫酷实战,检测密码强度值

在前端项目开发中&#xff0c;确保用户密码的强度是保护账户安全的重要措施。本文将演示如何使用Vue 3实现一个简单的密码强度检测功能。通过实时反馈&#xff0c;帮助用户创建更安全的密码&#xff0c;从而提升整体系统的安全性。无论您是前端开发新手还是经验丰富的开发者&am…

实验9 静态路由配置

实验9 静态路由配置 一、 原理描述二、 实验目的三、 实验内容四、 实验配置五、 实验步骤 一、 原理描述 网络中的每个路由器都会维护一张路由表或转发表。路由表的表项记录着目的网络信息以及下一跳I 地址。路由表可以手动配置&#xff0c;也可以通过路由算法动态生成。静态…

.NET最新漏洞 | 某SLMS系统存在SQL注入

01阅读须知 此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等&#xff08;包括但不限于&#xff09;进行检测或维护参考&#xff0c;未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失&#xf…