Linux 进程间通信_匿名管道

1.程间通信目的

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

2.匿名管道

1.原理

 上图表示进程打开了一个文件,每一个进程都有一个文件描述符表struct files_struct,

根据文件的路径在磁盘中找到文件的属性和内容,建立文件内核缓冲区 和 文件描述符struct file 里面有指向inode(文件属性)和文件内核缓冲区的指针。然后把文件描述符指针按由小到大的顺序填入文件描述符表的fd_arry[]数组中最后返回下标。

那如果以该进程为父进程创建子进程会是什么样的?

fork()创建一个子进程,肯定会把task_struct struct files_struct这些进程部分复制下来,

struct file不属于进程的一部分,但父子进程需要独立读写文件,也就意味着struct file里面的pos不同pos 通常指的是文件的当前偏移量,即下一个读写操作将从文件的哪个位置开始。),需要子进程复制一份。inode对文件的管理一份就够了,文件内核缓冲区是系统提供的,系统服务每个进程。

那父子进程如何完成通信呢?

父子进程在同一个文件的文件内核缓冲区进行操作,那文件内核缓冲区的内容要不要刷新到磁盘呢?这个文件的作用就是为了让进程间相互通信,没必要保存到磁盘。

有没有一种特殊的文件只用于进程间的通信呢?

管道

父进程读写打开管道,fork()创建子进程。父进程关闭读端,子进程关闭写端。父进程向管道写入数据,子进程可以随时从管道读取数据,而不会干扰彼此的读写操作。形成单向通信.

可以不关读端吗?

建议关,因为管道的设计就是为了单向通信父进程没必要去进行读操作,不关浪费数组资源,文件描述符泄漏。还有可能会进行误操作。

补充:关于重定向 >

./cout.c > test 表示把cout.c文件输出的内容重定向到test文件中。但比不上所有的打印信息都会重定向到test文件中,错误流的信息并不会重定向到test,而是打印到显示器上。

我们知道文件描述符 0输入流 1输出流 2错误流 ,

./cout.c > test 完整的表示是 ./cout.c 1>test 

如果想把错误流也重定向到test文件中

./cout.c &> test 这里的&表示将标准错误与标准输出一起处理。

或者

./cout.c 1>test 2>&1 

>&表示将文件描述符的目标重定向。

2>&1 的意思是将标准错误重定向到标准输出所指向的位置,也就是test文件

2.pipe()系统调用

pipe()系统调用创建一个管道。

#include <unistd.h>int pipe(int fd[2]);

参数:int fd[2]是一个输出行参数,返回文件描述符,fd[0]以读方式打开管道(读端)

fd[1]以写方式打开管道(写端)

返回值:成功返回0 失败返回-1 error

#include <iostream>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>int main()
{// 1.创建管道int fd[2] = {0};int n = pipe(fd);if (n == -1){std::cerr << "pipe error" << std::endl;return -1;}// 2.创建子进程pid_t id = fork();if (id < 0){std::cerr << "fork error" << std::endl;return -2;}if (id == 0){int count = 0;// 子进程 关闭读端close(fd[0]);while (1){close(fd[0]);std::string message = "hello ";message += std::to_string(getpid());message += ",";message += std::to_string(count++);// 写入管道int n = write(fd[1], message.c_str(), message.size());sleep(2);}exit(0);}else{char buff[1024];// 父进程 关闭写端close(fd[1]);// 从管道中读while (1){int n = read(fd[0], buff, 1024);if (n > 0){// 读到数据buff[n] = '\0'; // 系统字符串没有规定以0结尾std::cout << "子进程->父进程 message:" << buff << std::endl;}else if (n == 0){// 写端关闭 读到结尾break;}}int status;pid_t rid = waitpid(id, &status, 0);if (rid == -1){std::cerr << "waitpid error" << std::endl;return -3;}//int 16字节 前7位退出信号 后8位退出码std::cout<<"子进程pid"<<rid<<"退出码"<<((status<<8)&0xFF)<<"退出信号"<<(status&0x7F);}return 0;
}

上面是子进程写入,父进程读入并输出。

root@hcss-ecs-178e:~/dir1# ./pipe
子进程->父进程 message:hello 8128,0
子进程->父进程 message:hello 8128,1
子进程->父进程 message:hello 8128,2
子进程->父进程 message:hello 8128,3
子进程->父进程 message:hello 8128,4
子进程->父进程 message:hello 8128,5
子进程->父进程 message:hello 8128,6
root@hcss-ecs-178e:~# ps axj|head -1;ps axj|grep pipePPID     PID    PGID     SID TTY        TPGID STAT   UID   TIME COMMAND7039    8127    8127    7039 pts/2       8127 S+       0   0:00 ./pipe8127    8128    8127    7039 pts/2       8127 S+       0   0:00 ./pipe7918    8132    8131    7918 pts/3       8131 S+       0   0:00 grep --color=auto pipe

子进程不断向管道内写入,父进程读入并输出。

3.匿名管道的四种情况

1.管道为空&&管道正常 read会阻塞

子进程写入的速度小于父进程读入的速度,read会阻塞。

2.管道为满&&管道正常 wirte会阻塞

父进程读入速度小于子进程写入的速度,wirte会阻塞。

子进程每次写入一个字符,re表示写入多少字符。

让父进程读入一次就停止,子进程不停写 直到写满管道 wirte阻塞。

65536/1024=64KB 可见管道一次性最大存入64KB数据,父进程读入,子进程才能进行写入。也就意味着父进程读过后的内容在管道内不会保存。

3.管道写端关闭,读端继续。读端读到0,表示读到文件结尾。

 子进程只写入一次

父进程读到0,buff为空,意味着管道为空,读到结尾。退出返回退出码 退出信号

4.写端正常,读端关闭。OS会直接杀死进程

子进程写入管道就是为了让父进程读,如果读端关闭,意味着管道就没有存在的意义,会被系统杀死。

父进程读一次就关闭读端

可以看到退出信号为13,它表示一个进程试图向一个已关闭的管道或套接字写入数据。这种情况下,操作系统会终止该进程,通常会导致进程接收到该信号。

管道的特性

  1. 单向通信管道通常是单向的,数据从一个进程流向另一个进程。可以使用两个管道实现双向通信。

  2. 缓冲区:管道有一个内置的缓冲区,可以暂时存储数据。写入操作不会立即导致读取操作,因此可以在某些情况下实现异步通信。同步互斥

  3. 匿名性:在 Unix 和类 Unix 系统中,匿名管道不具名,不需要在文件系统中创建实体。它们只存在于相关联的进程之间。

  4. 阻塞行为:默认情况下,管道的读写操作是阻塞的。写入端在缓冲区满时会阻塞,读取端在管道为空时会阻塞。这可以帮助协调两个进程的执行。

  5. 进程关系:通常,管道用于父进程与子进程之间的通信。子进程可以继承父进程创建的管道描述符。

  6. 资源释放:当管道的最后一个读取端被关闭时,所有写入该管道的进程都会收到 SIGPIPE 信号,这可能导致它们终止。生命周期随进程

  7. 大小限制:管道的缓冲区大小通常受到操作系统的限制,不同系统的大小可能不同。

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

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

相关文章

vue3+vite 部署npm 包

公司需要所以研究了一下怎么部署安装&#xff0c;比较简单 先下载个vue项目 用vue脚手架安装vue3项目 删掉App.vue 中的其它组件 npm create vuelatest 开始写自定义组件 新建一个el-text 组件, name是重点&#xff0c;vue3中也得这么导出name属性 <script> export de…

JAVA-----线程池

目录 1.简单理解一下线程池 2.线程池参数 3.Executors ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ ​​​​​​​ 1.简单理解一下线程池 线程池&#xff0c;就是用来存储线程的&#xff0c;然后如果有任务传进线程池…

PortQry下载安装使用教程(超详细),Windows测试UDP端口

《网络安全自学教程》 PortQry是微软官方提供的一款TCP/IP连接「排障工具」&#xff0c;用来「检查」TCP/UDP「端口状态」。 平时检查端口状态&#xff0c;最常用的是telnet&#xff0c;但它是基于TCP协议的&#xff0c;无法检测「UDP端口」&#xff0c;这篇文章教大家如何在W…

Flink-cdc Schema Evolution 详解

Flink-cdc Schema Evolution 详解 github原文 glimpse flink-cdc-3 glimpse 源码基于 ~/project/flink_src/flink-cdc master !4 ❯ git remote -v origin https://github.com/apache/flink-cdc.git (fetch) origin https://github.com/apache/flink-cdc.git (push) ~/p…

介绍一款Java开发的企业接口管理系统和开放平台

介绍一款Java开发的企业接口管理系统和开放平台&#xff0c;YesApi接口管理平台Java版本。该系统基于Java开发&#xff0c;可以帮助企业进行统一接口管理、API接口开放&#xff0c;以及用于PaaS系统和SaaS产品平台的快速二次开发和搭建。 一、系统概述 YesApi接口大师&#x…

ClickHouse 5节点集群安装

ClickHouse 5节点集群安装 在此架构中&#xff0c;配置了五台服务器。其中两个用于托管数据副本。其他三台服务器用于协调数据的复制。在此示例中&#xff0c;我们将创建一个数据库和表&#xff0c;将使用 ReplicatedMergeTree 表引擎在两个数据节点之间复制该数据库和表。 官…

RHCE作业二

1.要求&#xff1a; 配置nginx服务通过ip访问多网站 2. 1关闭防火墙 2创建ip 3配置 4创建文件 5测试

logback 如何将日志输出到文件

如何作 将日志输出到文件需要使用 RollingFileAppender&#xff0c;该 Appender 必须定义 rollingPolicy &#xff0c;另外 rollingPollicy 下必须定义 fileNamePattern 和 encoder <appender name"fileAppender" class"ch.qos.logback.core.rolling.Rollin…

二、Spring的执行流程

文章目录 1. spring的初始化过程1.1 ClassPathXmlApplicationContext的构造方法1.2 refresh方法&#xff08;核心流程&#xff09;1.2.1 prepareRefresh() 方法1.2.2 obtainFreshBeanFactory() 方法1.2.3 prepareBeanFactory() 方法1.2.4 invokeBeanFactoryPostProcessors() 方…

shodan2---清风

注&#xff1a;本文章源于泷羽SEC&#xff0c;如有侵权请联系我&#xff0c;违规必删 学习请认准泷羽SEC学习视频:https://space.bilibili.com/350329294 实验一&#xff1a;search 存在CVE-2019-0708的网络设备 CVE - 2019 - 0708**漏洞&#xff1a;** 该漏洞存在于远程桌面…

解读数字化转型的敏捷架构:从理论到实践的深度分析

在当今数字经济的推动下&#xff0c;企业要在瞬息万变的市场中保持竞争力&#xff0c;数字化转型已经不再是一种选择&#xff0c;而是不可避免的战略需求。然而&#xff0c;企业如何从理论到实践进行有效的转型&#xff0c;尤其是在复杂的技术环境中&#xff0c;如何通过正确的…

来源爬虫程序调研报告

来源爬虫程序调研报告 一、什么是爬虫 爬虫&#xff1a;就是抓取网页数据的程序。从网站某一个页面&#xff08;通常是首页&#xff09;开始&#xff0c;读取网页的内容&#xff0c;找到在网页中的其它链接地址&#xff0c;然后通过这些链接地址寻找下一个网页&#xff0c;这…

中小型门诊管理系统源码,云诊所管理系统源码,前端技术栈:Vue 2 , Vite , Vue Router 3

中小型门诊管理系统源码&#xff0c;云诊所管理系统源码&#xff0c; 前端技术栈&#xff1a;Vue 2 Vite Vue Router 3 Vuex 3 Element Plus Axios TypeScript Quill Election 后端技术栈&#xff1a;Spring Boot MyBatis MyBatis-Plus Spring Security Swagger2 …

使用Python计算相对强弱指数(RSI)进阶

使用Python计算相对强弱指数&#xff08;RSI&#xff09;进阶 废话不多说&#xff0c;直接上主题&#xff1a;> 代码实现 以下是实现RSI计算的完整代码&#xff1a; # 创建一个DataFramedata {DATE: date_list, # 日期CLOSE: close_px_list, # 收盘价格 }df pd.DataF…

基于丑萌气质狗--C#的sqlserver学习

#region 常用取值 查询List<string> isName new List<string> { "第一", "第二", "第三", "第四" }; List<string> result isName.Where(m > m "第三").ToList();MyDBContext myDBnew MyDBContext(…

【数据分享】中国汽车市场年鉴(2013-2023)

数据介绍 在这十年里&#xff0c;中国自主品牌汽车迅速崛起。吉利、长城、比亚迪等品牌不断推出具有竞争力的车型&#xff0c;在国内市场乃至全球市场都占据了一席之地。同时&#xff0c;新能源汽车的发展更是如日中天。随着环保意识的提高和政策的大力支持&#xff0c;电动汽车…

CSS伪元素以及伪类和CSS特性

伪元素&#xff1a;可以理解为假标签。 有2个伪元素 &#xff08;1&#xff09;::before &#xff08;2&#xff09;::after ::before <!DOCTYPE html> <html> <head><title></title><style type"text/css">body::before{con…

Android简单控件实现简易计算器

学了一些Android的简单控件&#xff0c;用这些布局和控件&#xff0c;设计并实现一个简单计算器。 计算器的界面分为两大部分&#xff0c;第一部分是上方的计算表达式&#xff0c;既包括用户的按键输入&#xff0c;也包括计算结果 数字&#xff1b;第二部分是下方的各个按键&a…

【redis】初识非关系型数据库——redis

W...Y的主页 &#x1f60a; 代码仓库分享&#x1f495; 初识 Redis Redis是⼀种基于键值对&#xff08;key-value&#xff09;的NoSQL数据库&#xff0c;与很多键值对数据库不同的是&#xff0c;Redis 中的值可以是由string&#xff08;字符串&#xff09;、hash&#xff0…

基于协同过滤算法的个性化课程推荐系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…