010 Linux 进程间通信_匿名管道

前言

本文将会向你介绍匿名管道的原理以及用法,以及管道的使用存在的情况和管道的特性

文章重点

重点:匿名管道的原理,使用情况,以及特性

进程间通信

进程间通信的本质:

让不同的进程先看到同一份资源,这个资源不能由A,B进程提供,但能够被进程申请,资源通常都是由OS提供

进程间通信目的:

数据传输:一个进程需要将它的数据发送给另一个进程 资源共享:多个进程之间共享同样的资源。
通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止 时要通知父进程)。
进程控制:有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另
一个进程的所有陷入和异常,并能够及时知道它的状态改变

进程间通信分类

一、管道
匿名管道pipe
命名管道
二、System V IPC
System V 消息队列
System V 共享内存
System V 信号量
三、POSIX IPC
消息队列
共享内存
信号量
互斥量
条件变量
读写锁

今天要介绍的就是进程间通信的其中一种形式管道——匿名管道

什么是管道

在刚学linux的时候,在linux常见指令的那一讲,我们介绍过 | 管道符。 Linux管道符“|”用于将一个命令的输出传递给另一个命令作为输入。基本用法如下: command1 | command2

什么是匿名管道

匿名管道是通过调用系统函数pipe()创建的,不需要指定一个路径来标识管道。它只是一个临时的通道,存在于内存中,只能用于具有亲缘关系的进程之间通信(后续使用fork函数来实现)。

匿名管道的实现原理

首先要让不同的进程看到同一份资源,通过fork函数创建子进程,这样一来,子进程就会拷贝父进程的文件描述符表,再通过pipe创建匿名管道,父子进程通过相同的文件描述符指向同一个文件,意味着它们指向同一个页缓冲区,再用系统调用接口write写入数据到管道,read从管道中读取数据,即可完成父子进程之间的通信

在这里插入图片描述
pipe函数的用法

头文件:#include <unistd.h>
功能:创建一无名管道
原型 int pipe(int fd[2]);
参数 fd:文件描述符数组,其中fd[0]表示读端, fd[1]表示写端
返回值:成功返回0,失败返回错误代码
pipe函数的参数是一个输出型参数,返回两个文件描述符。管道被创建时,会需要使用两个文件描述符,一个文件描述符用于向管道写数据,一个文件描述符用于从管道读数据

在这里插入图片描述

首先通过pipe函数打开一个文件的读写端
在这里插入图片描述
通过fork函数,子进程能够继承读写端
在这里插入图片描述
再进行适当的关闭读写端(保留一个读一个写),这样未来能形成单向通道
在这里插入图片描述

创建管道并通信

这里设计的是让子进程写入,让父进程读取(这样做的好处是当子进程退出时,可以通过wait等待获取子进程的退出错误码)

#include <iostream>
#include <cassert>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#define MAX 100using namespace std;
int main()
{//创建管道int pipefd[2] = {0};int n = pipe(pipefd);//判断是否成功(一般都会成功,有确定预测的用assert,不确定的用if)assert(n==0);//防止在release模式下,assert失效,后续不会使用n会告警//void(n);cout << "pipefd[0]:" << pipefd[0] << ",pipefd[1]:" << pipefd[1] << endl;//创建子进程pid_t id = fork();//判断是否创建失败if(id < 0){perror("fork");return 1;}//子进程else if(id == 0){close(pipefd[0]);     //关闭读通道int cnt = 10;while(cnt){char message[MAX];snprintf(message, sizeof(message), "hello father, I am child, Mypid:%d, cnt: %d", getpid(), cnt);cnt--;//将字符串message写入到管道中write(pipefd[1], message, strlen(message));sleep(1);   //让子进程写慢些// char c = 'F';// write(pipefd[1], &c, 1);// cnt++;// cout << cnt << ":" << "writing..." << endl;}exit(0);}//父进程close(pipefd[1]);   //关闭写通道//TODOchar buffer[MAX];while(true){sleep(1);//从文件描述符对应的管道里读取数据,并将数据存储到buffer中size_t n = read(pipefd[0], buffer, sizeof(buffer) - 1);if(n > 0){buffer[n] = 0;cout << getpid() << " -> "<< " " << "child sends: " << buffer << " to me!" << endl; }else if(n == 0){   cout << "father return val(n):" << n << endl;cout << "child quit, me too!!!" << endl;sleep(1);break;}}   cout << "finish reading..." << endl;//写端已经退出,读完后关闭读端close(pipefd[0]);pid_t rid = waitpid(id, nullptr, 0);if(rid == id){cout << "wait success" << endl;}return 0;
}

管道的四种情况

1、如果管道没有数据了,读端必须等待,直到有数据为止

写入一条数据后,就让子进程进入休眠状态
在这里插入图片描述
现象:读端不再打印(读取数据),等待子进程写入
在这里插入图片描述

2、正常情况:如果管道被写满了,那么写端必须等待,直到有空间为止(读端读走数据)

让读端先睡一会,让写端一次写一个字节
在这里插入图片描述
现象:这里会将管道写满64KB,然后就不再写入了
在这里插入图片描述

3、写端关闭,读端一直读,读端会读到read返回值为0,表示读到文件结尾

让子进程写5条就退出
在这里插入图片描述
现象:read返回值为0,表示读完了
在这里插入图片描述

4、读端关闭(读一次直接break,然后关掉读端的文件描述符),写端一直写,写入就没有意义了,写端直接挂掉了,对于操作系统来说,不会做消耗资源的事情(直接杀掉写端进程,通过向目标进程发送sigpipe(13)信号,终止目标进程)

直接在最后break
在这里插入图片描述

现象:写端挂掉了
在这里插入图片描述
在这里插入图片描述

管道的五种特性

1、匿名管道,可以允许具有血缘关系的进程之间进行进程间通信,常用于父子,兄弟,爷孙都可以
毫不相关的进程,是不能通过这种管道进行通信的,是通过fork来通信的
2、匿名管道,默认给读写端要提供同步机制(没有管道的时候,父子进程都向显示器打印,你打你的,我打我的,有了管道,读端就等待写端)
3、匿名管道是面向字节流的,写10次,可以读一次全部读完,也可以一条条读,怎么write和怎么read无关
4、管道的生命周期是随进程的(整个管道会被释放掉,管道也是底层文件,父子进程退出后,管道没有人用了,会被os回收)
5、管道是单向通信的一种特殊情况

小结

今日的分享就到这里啦,如果本文存在疏漏或错误的地方,还请您能够指出!

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

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

相关文章

c#使用log4net的3种调用方法

https://blog.csdn.net/summer_top/article/details/107961245 第一步&#xff1a;下载log4net。 右键项目引用&#xff0c;进入管理NuGet包。 搜索log4net&#xff0c;下载安装。 第二步&#xff1a;创建LogHelper类。 public class LogHelper { private LogHelp…

部署PhotoMaker通过堆叠 ID 嵌入自定义逼真的人物照片

PhotoMaker只需要一张人脸照片就可以生成不同风格的人物照片&#xff0c;可以快速出图&#xff0c;无需额外的LoRA培训。 安装环境 python 3.10gitVisual Studio 2022 安装依赖库 git clone https://github.com/bmaltais/PhotoMaker.git cd PhotoMaker python -m venv venv…

C++_STL使用手册

STL基础 STL全称为 standard template library&#xff0c;中文可译为标准模板库或者泛型库&#xff0c;其包含有大量的模板类和模板函数&#xff0c;是 C 提供的一个基础模板的集合;STL由容器、算法、迭代器、函数对象、适配器、内存分配器这 6 部分构成&#xff0c;其中后面…

为什么这么多项目经理选择考取PMP证书?

PMP认证是目前国际上项目管理领域认可度和含金量最高的证书。通过PMP就证明你的项目管理水平达到了国际标准&#xff0c;有能力从事项目管理工作&#xff0c;普通人需要很多年才能积累悟出的职场做事逻辑&#xff0c;学一个PMP就搞定了。考证花的钱&#xff0c;持证后加薪分分钟…

传感器为智能化基础,L3车规落地打开激光雷达新空间(下)

3 L3车规落地打开激光雷达新空间&#xff0c;未来进一步迭代降本 3.1 技术落地&#xff0c;智能驾驶迈入L3关键节点 L3是区分辅助驾驶与智能驾驶的关键节点&#xff0c;L0-L2“人为主、车为辅”&#xff0c;L3之后“车为主、人为辅”。随着技术持续升级&#xff0c;智能驾驶…

洛谷 P2249 【深基13.例1】查找

思路&#xff1a;这是最典型和基础的二分查找题&#xff0c;因为符合单调性和有界性&#xff0c;如果直接暴力查找的话&#xff0c;会超时&#xff0c;只需要用一下二分即可 左边界为&#xff1a;0&#xff08;因为编号最小为1&#xff09; 右边界为&#xff1a;n1&#xff0…

LeetCode # 206. 反转链表

206. 反转链表 题目 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1] 示例 2&#xff1a; 输入&#xff1a;head [1,2] 输出&#xff1a;[2,1] 示例…

Java SpringBoot 获取 yml properties 自定义配置信息

Java SpringBoot 获取 yml properties 自定义配置信息 application.yml server:port: 9090servlet:context-path: /app第一种方法 HelloController package com.zhong.demo01.controller;import org.springframework.beans.factory.annotation.Value; import org.springfram…

qt5与qt6的cmake区别

文章目录 使用cmake构建qt项目&#xff0c;坑很多。一是本身就麻烦&#xff0c;二是&#xff0c;确实坑&#xff0c;因为不同的qtcreator版本&#xff0c;选了不同的kits&#xff08;套件&#xff09; 生成的CMakeList.txt文件也不一样。 如果可以的话都选择Qt6的相关选项&…

人工智能到深度学习:药物发现的机器智能方法(综述学习)

Artificial intelligence to deep learning: machine intelligence approach for drug discovery - PubMed (nih.gov) 人工神经网络、深度神经网络、支持向量机、分类和回归、生成对抗网络、符号学习和元学习是应用于药物设计和发现过程的算法的例子。人工智能已应用于药物设计…

【Spring】回顾反射机制

一、分析方法四要素 package org.qiu.reflect;/*** author 秋玄* version 1.0* email qiu_2022aliyun.com* project Spring* package org.qiu.reflect* date 2022-11-11-17:26* since 1.0*/ public class SomeService {public void doSome(){System.out.println("public …

森林监测VR虚拟情景再现系统更便利

AI人工智能技术已经逐渐渗透到各个领域&#xff0c;为我们的生活带来了诸多便利。在虚拟仿真教学领域&#xff0c;AI技术的应用也日益丰富&#xff0c;为虚拟情景交互体验带来了前所未有的好处。 提高VR虚拟情景的逼真度 通过深度学习和计算机视觉等技术&#xff0c;AI/VR虚拟现…

Vue3 + xterm + eventSource

xterm 是一个使用 typescript 编写的前端终端组件&#xff0c;可以在浏览器中实现一个命令行终端应用&#xff0c;通常与 websocket一起使用。 一、安装 pnpm install xterm or yarn add xterm or pnpm install xterm二、代码实现: 实现日志展示 <template><a-modal…

从 0 到 1 搭建亿级商品 ES 搜索引擎

建设并维护一个亿级的搜索引擎并非易事&#xff0c;也不存在一劳永逸的最优治理方法。本文是在实践中不断学习和总结的成果&#xff0c;介绍了如何搭建一个可支持从千万级到亿级商品量级的搜索系统&#xff0c;并实现查询总 QPS 从百级增长到千级&#xff0c;写入总 QPS 从百级…

androidapp的开发流程,王者笔记

昨天去面了一家公司&#xff0c;价值观有受到冲击。 面试官技术方面没的说&#xff0c;他可能是个完美主义的人&#xff0c;无论什么事情到了他那里好像都有解决的方案&#xff0c;我被说的无所适从&#xff0c;感觉他很厉害。 但我不能认可的是&#xff0c;面试官觉得加班是…

nextjs13如何进行服务端渲染?

目录 一、创建一个新项目 二、动态获取后端数据进行服务端渲染出现的问题 三、nextjs13如何进行服务端渲染 nextjs13是nextjs的一个重大升级&#xff0c;一些原本在next12当中使用的API在nextjs13上使用十分不便。本文将着重介绍在nextjs13及以上版本当中进行服务端渲染的方…

Linux - 基本指令

1、ls 指令 语法&#xff1a;ls [选项][目录或文件] 功能&#xff1a;对于目录&#xff0c;该命令列出该目录下的所有子目录与文件。对于文件&#xff0c;将列出文件名以及其他信息。 常用选项&#xff1a; -a 列出目录下的所有文件&#xff0c;包括以 . 开头的隐含文件-l …

Docker本地部署GPT聊天机器人并实现公网远程访问

文章目录 前言1. 拉取相关的Docker镜像2. 运行Ollama 镜像3. 运行Chatbot Ollama镜像4. 本地访问5. 群晖安装Cpolar6. 配置公网地址7. 公网访问8. 固定公网地址9. 结语 前言 随着ChatGPT 和open Sora 的热度剧增,大语言模型时代,开启了AI新篇章,大语言模型的应用非常广泛&…

Linux Shell脚本练习(一)

一、 Linux下执行Shell脚本的方式&#xff1a; 1、用shell程序执行脚本&#xff1a; a、根据你的shell脚本的类型&#xff0c;选择shell程序&#xff0c;常用的有sh&#xff0c;bash&#xff0c;tcsh等 b、程序的第一行#!/bin/bash里面指明了shell类型的&#xff0c;比如#!/…