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.mzph.cn/diannao/58132.shtml

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

相关文章

家庭网络光猫到客厅通过VLAN实现单线复用

大部分家庭装修时没有提前考虑网线分布&#xff0c;一般装修公司都是从各个房间拉一根网线到弱电箱&#xff0c;就结束了&#xff0c;如下图。但是弱电箱在大部分家庭&#xff0c;空间非常小&#xff0c;很难放下一些常见的路由器&#xff0c;花大价钱买了个路由器作为主路由&a…

【C++】继承与模板

继承 1.继承的概念 概念&#xff1a;继承(inheritace)机制是面向对象程序设计使代码可以复用的最重要的手段&#xff0c;它允许程序员在保持原有类特性的基础上进行扩展&#xff0c;增加功能&#xff0c;这样产生新的类&#xff0c;称之为派生类。继承呈现了面向对象程序设计的…

信息安全工程师(68)可信计算技术与应用

前言 可信计算技术是一种计算机安全体系结构&#xff0c;旨在提高计算机系统在面临各种攻击和威胁时的安全性和保密性。 一、可信计算技术的定义与原理 可信计算技术通过包括硬件加密、受限访问以及计算机系统本身的完整性验证等技术手段&#xff0c;确保计算机系统在各种攻击和…

融合DevOps打造企业高效流程体系的实践与探索

一、引言 转眼间&#xff0c;我已毕业十多年&#xff0c;在IT领域深耕不辍&#xff0c;曾涉足全栈研发、大数据研发、架构设计与项目管理等多个岗位&#xff0c;更主导过公司从市场到交付再到运营的全链条流程建设。在这漫长的职业生涯中&#xff0c;一个问题始终萦绕在我心头&…

Linux安装部署数据库:PostgreSQL14

Linux安装部署数据库&#xff1a;PostgreSQL14 一、安装环境1、虚拟机环境2、下载安装包 二、安装步骤1、在线安装 PGSQL2、离线安装 PGSQL3、源码安装 PGSQL 三、基本操作1、初始化配置2、数据库登录3、常用命令项 四、常见问题1、对用户 "postgres" 的对等认证失败…

App测试环境部署

一.JDK安装 参考以下AndroidDevTools - Android开发工具 Android SDK下载 Android Studio下载 Gradle下载 SDK Tools下载 二.SDK安装 安装地址&#xff1a;https://www.androiddevtools.cn/ 解压 环境变量配置 变量名&#xff1a;ANDROID_SDK_HOME 参考步骤&#xff1a; A…

3GPP协议解读_NTN系列(一)_38.811_非地面网络(NTN)的背景、应用场景和信道建模

非地面网络 1. Scope4. 非地面网络背景介绍4.1 5G中的非地面网络4.2 非地面网络在5G中的用例4.3 卫星和空中接入网的架构4.4 卫星和空中接入网终端的特点4.5 空气/星载飞行器特性4.6 NTN的覆盖模式4.7 NTN网络架构选项4.8 频谱 5. 非地面网络应用场景5.1 应用场景概览5.2 属性介…

CHAPTER 14 Nonlinearity and Mismatc

CHAPTER 14 Nonlinearity and Mismatch 第6,7章我们介绍了两种非理想: 频率响应和噪声. 这一章我们介绍另外两种非理想现象: 非线性和失配. 我们首先定量化nonlinearity, 学习差分电路和反馈系统的非线性, 以及线性化技术. 然后学习差分电路中的失配和dc offset. 最后学习一些…

51单片机之蜂鸣器驱动

1.简介 蜂鸣器是一种一体化结构的电子讯响器&#xff0c;采用直流电压供电&#xff0c;广泛应用于计算机、打印机、 复印机、报警器、电子玩具、汽车电子设备、电话机、定时器等电子产品中作发声器件。蜂鸣器主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型。   压电式蜂鸣器主要…

【C++】vector<string>-动态数组存储多个string

#1024程序员节 | 征文# //demo #include <iostream> #include <vector> #include <string>using namespace std; int main() {// 创建一个存储字符串的向量vector<string> Record;// 向向量中添加字符串Record.push_back("example");Record…

Node-RED的面板的认识及操作

&#x1f3ac; 江城开朗的豌豆&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 &#x1f4dd; 个人网站 :《 江城开朗的豌豆&#x1fadb; 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 &#x1f4d8; 文章引言 &#x1f4df; 面板…

深入探索:深度学习在时间序列预测中的强大应用与实现

引言&#xff1a; 时间序列分析是数据科学和机器学习中一个重要的研究领域&#xff0c;广泛应用于金融市场、天气预报、能源管理、交通预测、健康监控等多个领域。时间序列数据具有顺序相关性&#xff0c;通常展示出时间上较强的依赖性&#xff0c;因此简单的传统回归模型往往…

论文略读:Less is More: on the Over-Globalizing Problem in Graph Transformers

2024 ICML 主要观点&#xff1a;Graph Transformer 中的过全局化问题 (Over-Globalizing Problem) 当前 Graph Transformer 的注意力机制过度关注那些远端节点&#xff0c;而实际上包含了大部分有用信息的近端节点则被相对忽视了——>提出了一种新的采用协同训练的两级全局…

【Ubuntu】服务器系统重装SSHxrdpcuda

本文作者&#xff1a; slience_me Ubuntu系统重装操作合集 文章目录 Ubuntu系统重装操作合集1.1 系统安装&#xff1a;1.2 安装openssh-server更新系统包安装OpenSSH服务器检查SSH服务的状态配置防火墙以允许SSH测试SSH连接配置SSH&#xff08;可选&#xff09; 1.3 安装远程连…

力扣之612.平面上的最近距离

文章目录 1. 612.平面上的最近距离1.1 题目说明1.2 准备数据1.3 解法1.4 结果截图 1. 612.平面上的最近距离 1.1 题目说明 Point2D 表&#xff1a; ----------------- | Column Name | Type | ----------------- | x | int | | y | int | ----------------- (x, y) 是该表的…

微信小程序——消息订阅

首先用到的就是wx.requestSubscribeMessage接口。 注意&#xff1a;用户发生点击行为或者发起支付回调后&#xff0c;才可以调起订阅消息界面 requestSubscribeMessage() {uni.requestSubscribeMessage({tmplIds: [],//需要订阅的消息模板的id的集合&#xff0c;一次调用最多可…

阿里云用STS上传oss的完整程序执行流程图 和前端需要哪些参数uniapp

H5 微信小程序可用的前端直传阿里云OSS(STS临时凭证前端签名)直接下载插件 阿里云sts使用官方文档 下面是原理说明&#xff1a; 前端上传文件到阿里云OSS需要携带的具体参数&#xff1a; 从服务器获取的 STS 凭证&#xff1a; // 这些参数需要从你的后端服务器获取 {acc…

66Analytics 汉化版,网站统计分析源码,汉化前台后台

66Analytics 汉化版,网站统计分析源码,汉化前台后台 本源码汉化前台后台&#xff0c;非其他只汉化前台版 网络分析变得容易。自托管、友好、一体化的网络分析工具。轻量级跟踪、会话回放、热图、用户旅程等 简单、好看、友好-大多数网络分析解决方案做得太多了&#xff0c;在大…

Linux 重启命令全解析:深入理解与应用指南

Linux 重启命令全解析&#xff1a;深入理解与应用指南 在 Linux 系统中&#xff0c;掌握正确的重启命令是确保系统稳定运行和进行必要维护的关键技能。本文将深入解析 Linux 中常见的重启命令&#xff0c;包括功能、用法、适用场景及注意事项。 一、reboot 命令 功能简介 re…

商家转账到零钱功能:便捷高效的资金流转新方式

在当今数字化时代&#xff0c;线上支付已成为商业活动中不可或缺的一部分。为了满足商家与消费者之间日益增长的多样化需求&#xff0c;各大支付平台纷纷推出了创新的支付解决方案。其中&#xff0c;“商家转账到零钱”功能便是一项备受瞩目的创新服务&#xff0c;它不仅极大地…