进程通信方式——管道

什么是管道

管道是进程间通信的一种方式,它的本质其实是内核中的一块内存(或者说是内核缓冲区),这块区域的数据存储在一个环形队列,不过由于管道使用的是内核里面 的内存,所以我们无法对管道里面的数据进行直接操作,只能在管道的两端读/写数据。

管道的特点

  • 管道数据是基于队列来维护的

  • 管道对应的内核缓冲区大小的固定,默认4K

  • 管道分为两部分:读端和写端(队列的两端),数据从写端进入管道,从端流出管道

  • 管道的数据只能读一次,可以理解数据是在管道里面流动,由一端流向另一端.

  • 对管道的操作(读,写)默认是阻塞的

    • 读管道:管道中没有数据,读操作被阻塞,当管道中有数据之后阻塞才能解除。
    • 写管道:管道被写满了,写数据的操作被阻塞,当管道变为不满的状态,写阻塞解除。
    • Linux的文件IO函数:
    ssize_t read(int fd,void *buf,size_t count);
    ssize_t write(int fd,const void *buf,size_t count);
    

匿名管道

匿名管道的创建

匿名管道是管道的一种,匿名主要是指管道没有名字,但是本质是不变,它有管道的所有特性,匿名管道只能实现有血缘关系的进程间通信(父子进程,兄弟进程,爷孙进程,叔侄进程)

#include <unistd.h>
int pipe(int pipefd[2]);
  • 参数:传出参数,需要传递一个整形数组的地址,数组大小为 2,也就是说最终会传出两个元素
    • pipefd[0]: 对应管道读端的文件描述符,通过它可以将数据从管道中读出
    • pipefd[1]: 对应管道写端的文件描述符,通过它可以将数据写入到管道中
  • 返回值:成功返回 0,失败返回 -1

进程间的通信

在讲解进程间通过管道的提醒具体内容之前,我们先来看一个简单的样例:

#include <iostream>
#include <cstring>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/types.h>using namespace std;int main()
{int fd[2] ;//定义两个文件描述符int ret=pipe(fd);  //创建管道if(ret==-1){perror("pipe error");}int pid=fork();  //创建子进程if(pid==0){close(fd[0]);/*这里子进程关闭读端,保留写端,这里我们希望将原来的在终端输出的内容改为输入到管道给父进程读取*/dup2(fd[1],STDOUT_FILENO);//将输出位置重定向到管道上execlp("ps","ps","aux",NULL);perror("execlp error");}else if(pid>0)  //执行父进程操作{close(fd[1]); //关闭写端char buff[1024];//读管道 //管道无数据——> read函数阻塞//管道有数据——> read停止阻塞(如果正处于阻塞状态),读取数据(若管道已满,写操作阻塞);while(true){sleep(5);memset(buff,0,sizeof(buff));int len=read(fd[0],buff,sizeof(buff));if(len==0)  cout<<"pipe is empty"<<endl;cout<<"buff:"<<buff<<" "<<"len:"<<len<<endl;}wait(NULL); //等待子进程结束回收资源}return 0;
}

备注

  • 子进程中执行shell命令相对于启动一个磁盘程序,因此需求使用execl()/execlp()函数
    • execlp(“ps”,“ps”,“aux”,NULL)
  • 子进程中执行完shell命令直接就可以终端输出结果,这些消息传递父进程?
    • 进程数据传递需要管道,子进程需要将数据写入管道,父进程需要从管道中读取数据
    • 这里子进程想将终端输出结果写入管道,因此需要将标准输出重定向到管道
    • 这里父进程要等待子进程执行完shell命令释放子进程资源进而避免僵尸进程,因此需要使用wait()函数

有名管道

有名管道和匿名管道类似,但是有名管道可以用于无亲缘关系的进程间通信,之所以叫有名管道,是因为它在磁盘上有一个文件,类型为p,它的大小为0,因为它的内容还是存储在
内存缓存区,但是我们打开它可以获取文件蛮舒服,进而基于它们我们可以实现无血缘关系进程之间的通讯,同时由于有名管道式一个文件实体,所以我们创建文件时渝新欧下面两种:

  • 基于shell命令创建
mkfifo filename
  • 基于C语言创建
#include<sys/types.h>
#include<sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
  • 参数
    • pathname:文件名
    • mode:权限
  • 返回值
    • 成功:0
    • 失败:-1

基于有名管道实现进程间通信

  • 写进程
// 有名管道的写端
#include <string>
#include <iostream>
#include <fcntl.h>
#include <unistd.h>
#include <cstdio>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <cerrno>
#include <cstdlib>
#include <string.h>using namespace std;int main()
{int wfd=open("./testfifo",O_WRONLY);if(wfd==-1){perror("open");return -1;}cout<<"open success"<<endl;int i=0;while(i<100){char str[1024];memset(str,0,sizeof(str));sprintf(str,"hello world %d\n",i);int wn=write(wfd,"hello world",strlen("hello world"));if(wn<0){cerr<<"错误码:"<<errno<<",错误原因:"<<strerror(errno)<<endl;break;}if(wn>0){cout<<"write "<<wn<<" bytes"<<endl;}i++;sleep(1);}close(wfd);return 0;
}
  • 读进程
#include <iostream>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <cstring>using namespace std;int main()
{int rfd = open("./testfifo", O_RDONLY);if (rfd == -1){perror("open");return -1;}char buf[1024];while (true){memset(buf, 0, sizeof(buf));int len = read(rfd, buf, sizeof(buf) - 1); // 减去1以防止覆盖结束符if (len >0)   cout<<"receive: "<<buf<<endl;}close(rfd); // 关闭文件描述符return 0;
}

管道描述符的修改

// 管道操作眼需要创建对应两个文件描述符, 分别是管道的读端和写端,但是创建完管道后也可以将它们对应的属性进行修改(比如将阻塞改为非阻塞),步骤如下:// 1. 获取读端的文件描述符的flag属性
int flag = fcntl(fd[0], F_GETFL);
// 2. 添加非阻塞属性到 flag中
flag |= O_NONBLOCK;
// 3. 将新的flag属性设置给读端的文件描述符
fcntl(fd[0], F_SETFL, flag);
// 4. 非阻塞读管道
char buf[4096];
read(fd[0], buf, sizeof(buf));

备注:虽然可以修改但是一般不建议这么做,这里涉及的仅供参考。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

K8S:开源容器编排平台,助力高效稳定的容器化应用管理

云计算de小白 Kubernetes&#xff08;简称K8s&#xff09;是一个开源容器编排平台&#xff0c;用于自动化部署、扩展和管理容器化应用程序。 K8S诞生于Google&#xff0c;基于其多年在生产环境运行容器的经验&#xff0c;目前已成为现代微服务架构和云原生应用的核心技术。 图…

Excel-统计日期内的个数1月到12月

使用函数COUNTIFS&#xff08;范围,"条件",范围,"条件"&#xff09; COUNTIFS(Sheet!F2:F230,">2024-01-01",sheet!F2:F230,"<2024-01-31") COUNTIFS(sheet!F2:F230,">2024-02-01",sheet!F2:F230,"<2024-…

MKV转MP4丨FFmpeg的简单命令使用——视频格式转换

MKV是一种视频封装格式&#xff0c;很好用&#xff0c;也是OBS的默认推荐录制格式&#xff0c;因为不会突然断电关机而导致整个视频录制文件丢失。 但是MKV无法直接导入PR中剪辑&#xff0c;最直接的方法是将MKV转换为MP4格式&#xff0c;最方便且安全无损的转换方法便是用FFmp…

[Notepad++] 文本编辑器的下载及详细安装使用过程(附有下载文件)

程序员常用的文本编辑器Notepad&#xff0c;用于修改配置文件等 下载链接在文末 下载压缩包后解压 &#xff01;&#xff01;安装路径不要有中文 解压文件&#xff0c;得到 双击exe文件 选择简体中文&#xff0c;点击OK 点击下一步 点击“我接受” 更改安装目录&#xff0c;不…

Selenium入门

Selenium 是一个用于自动化 web 应用程序测试的工具&#xff0c;它支持多种浏览器和编程语言。 下载驱动程序&#xff1a;根据你的浏览器类型和版本&#xff0c;下载相应的 WebDriver。例如&#xff0c;Chrome 浏览器需要 ChromeDriver。 安装 Selenium 库 pip install sele…

什么是 Apache Ingress

Apache Ingress 主要用于管理来自外部的 HTTP 和 HTTPS 流量&#xff0c;并将其路由到合适的 Kubernetes 服务。 容器化与 Kubernetes 是现代云原生应用程序的基础。Kubernetes 的主要职责是管理容器集群&#xff0c;确保它们的高可用性和可扩展性&#xff0c;同时还提供自动化…

针对考研的C语言学习(定制化快速掌握重点5)

顺序表 特点&#xff1a; 写代码主要就是增删改查&#xff01;&#xff01;&#xff01; 写代码的边界性非常重要以及考研插入和删除的位置都是从1开始&#xff0c;而数组下标是从0开始 【注】下标和位置的关系 线性表最重要的是插入和删除会涉及边界问题以及判断是否合法 …

vue仿chatGpt的AI聊天功能--大模型通义千问(阿里云)

vue仿chatGpt的AI聊天功能–大模型通义千问&#xff08;阿里云&#xff09; 通义千问是由阿里云自主研发的大语言模型&#xff0c;用于理解和分析用户输入的自然语言。 1. 创建API-KEY并配置环境变量 打开通义千问网站进行登录&#xff0c;登陆之后创建api-key&#xff0c;右…

FRP安装配置详解

FRP 安装与配置详解 FRP&#xff08;Fast Reverse Proxy&#xff09;是一款内网穿透工具&#xff0c;它帮助内网设备通过公网服务器将服务暴露到外网。以下是详细的安装与配置步骤&#xff0c;帮助你快速部署 FRP。 一、安装 FRP 1. 下载 FRP FRP 支持多种系统平台&#xff…

Qt C++设计模式->享元模式

享元模式&#xff08;Flyweight Pattern&#xff09;是一种结构型设计模式&#xff0c;旨在通过共享相同对象来减少内存使用&#xff0c;尤其适合在大量重复对象的情况下。它通过将对象的可共享部分抽取出来&#xff0c;并在多个上下文中共享&#xff0c;从而避免对象的多次创建…

Tomcat为什么要打破双亲委派?怎么保证安全

Tomcat打破双亲委派模型的原因主要是为了解决Web应用程序中的类加载冲突问题&#xff0c;并提供更好的灵活性和可扩展性。在Java中&#xff0c;双亲委派模型是一种类加载机制&#xff0c;它确保了类加载的安全性和一致性&#xff0c;但在Web应用程序的场景下&#xff0c;它可能…

MySQL和Doris开窗函数LAG执行时的区别

目标表的表结构 CREATE TABLE point_value_status_color_tmp ( id bigint NOT NULL, org_id varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, device_id varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, origin_ti…

数据库课程设计案例:在线教育管理系统

一、项目背景 随着在线教育的兴起&#xff0c;传统的教学管理模式面临着新的挑战。在线教育管理系统旨在为学生、教师和管理员提供一个高效、便捷的学习与管理平台&#xff0c;以提升学习效果和管理效率。 二、系统功能需求 用户管理 用户注册与登录角色管理&#xff08;学生…

CSS面试真题 part1

CSS面试真题 part1 1、说说你对盒子模型的理解2、谈谈你对BFC的理解3、什么是响应式设计&#xff1f;响应式设计的基本原理是什么&#xff1f;如何做&#xff1f;4、元素水平垂直居中的方法有哪些&#xff1f;如果元素不定宽高呢&#xff1f;5、如何实现两栏布局&#xff0c;右…

目标检测——VOC2007数据集

目标检测入门code 文件目录 下载数据集——在官网下载VOC2007数据集 下载训练数据集 TRAIN data 下载测试数据集 TEST data 解压数据集 解压——训练数据集&#xff0c;在服务器上&#xff0c;目录为VOCdevkit 部分文件目录 全部文件总目录 解压——测试数据集 &#xff08;…

Unity 与虚幻引擎对比:两大游戏开发引擎的优劣分析

在游戏开发领域&#xff0c;Unity 和虚幻引擎&#xff08;Unreal Engine&#xff09;是两款最为知名且广泛使用的引擎。它们各有特点&#xff0c;适合不同类型的开发者和项目。在这篇博客中&#xff0c;我们将深入探讨这两大引擎的核心功能、适用场景、优缺点&#xff0c;以及如…

DMDSC更换DCR和VOTE磁盘

DMDSC更换DCR和VOTE磁盘 为了提高DMDSC集群运行速度和节点之间通信协调的效率&#xff0c;需要将运行在机械盘上的dcr和vote磁盘替换到SSD高效磁盘上。将原来200M的dcr和vote机械磁盘&#xff0c;换成500M的SSD高效磁盘。 磁盘替换规划信息如下所示&#xff1a; 信息说明 替…

什么是IPv6

目前国内的网络正在快速的向IPv6升级中&#xff0c;从网络基础设施如运营商骨干网、城域网&#xff0c;到互联网服务商如各类云服务&#xff0c;以及各类终端设备厂商如手机、电脑、路由器、交换机等。目前运营商提供的IPv6线路主要分为支持前缀授权和不支持前缀授权两种。 说…

Python酷玩之旅_如何连接MySQL(mysql-connector-python)

前言 Python作为数据科学、机器学习等领域的必选武器&#xff0c;备受各界人士的喜爱。当你面对不同类型、存储于各类介质的数据时&#xff0c;第一时间是不是要让它亮个相&#xff1f;做个统计&#xff0c;画个图表&#xff0c;搞个报表… 等等。 正如Java中的JdbcDriver一样…

真正的Open AI ——LLaMA颠覆开源大模型

1. LLaMA 简介 LLaMA&#xff08;Large Language Model Meta AI&#xff09;是由Meta&#xff08;原Facebook&#xff09;推出的一个大型语言模型系列&#xff0c;旨在通过更小的模型规模和更少的计算资源&#xff0c;实现与其他主流语言模型&#xff08;如GPT&#xff09;相媲…