进程间通信 管道

前言

ubuntu系统的默认用户名不为root的解决方案(但是不建议):轻量应用服务器 常见问题-文档中心-腾讯云 (tencent.com)

进程间通信的基本概念

进程间通信目的:进程间也是需要协同的,比如数据传输、资源共享、通知事件、进程控制

进程间通信的前提:让不同进程看到同一份OS中的资源(一段内存) 

  1. 一定是某个进程提出了进程间通信的请求,OS才会创建一个共享资源
  2. 为了防止进程在通信时直接访问OS,OS会提供很多系统调用接口
  3. OS创建的共享资源的不同 + OS提供的系统调用接口的不同 = 进程间通信会有不同的种类 

 注意事项:

1、进程间能通信不等于能一直通信,fork函数子进程继承父进程不属于进程间通信

2、进程间通信的成本可能会稍微高一点

进程间通信依赖的标准:system V标准(主要用于本地通信) 和posix标准

system V标准规定的三种进程间通信的方案:消息队列、共享内存、信号量

管道

基本概念:System V 标准中提供了多种 IPC 机制,如消息队列、共享内存和信号量,但是使用这些 IPC 机制需要考虑很多细节问题(例如缓冲区大小、同步与互斥等),并且需要编写复杂的代码来实现,而管道只需一条简单命令即可创建,并且它们支持两个相关联地运行在同一系统上地程序之间互相传输信息(管道是最初人们实现进程间通信的一种方式)

问题:为什么父子进程会向同一个显示器终端打印数据?

解释:进行写操作时,父子进程都会向同一个内核级文件缓冲区中写入(内核级文件缓冲区不属于任何文件)当操作系统定期刷新时会将该缓冲区中的内容刷新到指定的文件中(在这里就是显示器文件)

问题:进程怎么做到默认打开三个标准流0、1、2?

解释:因为所有的进程都是bash的子进程,当bash打开(指向这三个流的文件,具体细节不再描述)了,bash的子进程也就打开了

问题:为什么子进程主动close(0或1或2)不影响父进程继续使用显示器文件呢?

解释:struct file中存在一个内存级的引用计数,父子进程同时指向一个struct file则该引用计数为2,close子进程的某个标准流文件时,只会将该引用计数减一,父进程依然可以访问(file - > ref_count--; if(ref_count == 0)才会释放文件资源)

问题:什么是管道文件?

解释:内核级文件缓冲区(重新设计后的) + struct file,父子进程一个负责向内核级文件缓冲区中写,另一个读取内核级文件缓冲区中的内容就形成了进程间通信的定义(让不同的进程看到同一份OS中的资源,文件系统也属于OS),此外为了保证父子进程间通信的合理性,管道文件只允许单向通信,同时读取会发生数据紊乱

补充:为了提高进程间通信的效率,避免写入文件缓冲区后还要向磁盘文件中刷新,所以OS设计者基于原来内核级文件缓冲区的代码,在OS中重新设计了一个不需要向磁盘中定时刷新的内核级文件缓冲区 

问题:如何实现父进程读文件,子进程写文件?

解释:父进程仍然打开3号文件描述符close(4),子进程仍然打开4号文件描述符close(3)

问题:父子既然要关闭不需要的fd,为何之前还要打开?可以不关闭吗?

解释:①为了让子进程继承,通过继承后不用了再关闭的这种方式形成的进程间通信是由设计者深思熟虑后的结果(父进程只打开一个3后续子进程还要再关闭3再打开4,还不如父子进程都打开3和4按照实际情况再进行关闭,前者也可以但是后者更简单)可以不关闭但是可能会造成父子进程同时写入,所以建议关闭,同时由于存放文件描述符的是一个数组,数组是有大小范围的,所以如果为了保证通信的单向性子进程让某个文件描述符空闲,如果还有其它情况造成的文件描述符在数组中处于空闲状态,就会造成文件描述符泄漏

匿名管道

pipe函数

函数原型:int pipe(int pipefd[2]);

包含头文件:<unistd.h>

参数:输出型参数,是一个由两个整数构成的数组,第一个元素表示读端的文件描述符,第二个元素表示写端的文件描述符,写端和读端的文件描述符由OS自行填写

返回值:调用成功返回0,否则返回-1

功能:在OS中创建一个用于进程间通信的没有名字的内核级文件缓冲区,即匿名管道

注意事项:

1、pipe函数的底层是open函数,只不过这里不需要提供文件路径、文件名以及初始权限

2、如果想要双向通信可以使用两个管道

3、将pipe创建的内核级文件缓冲区叫做管道,是因为它在本质上还是一个内核级文件缓冲区,只不过正常情况下一个进程对文件进行写的时候就是写入内核级文件缓冲区然后由OS负责定时刷新到管道,而新建的缓冲区不会向磁盘中刷新而是刷新给进程,刷新的目的地改变了,只需将原来内核级文件缓冲区的代码稍加更改就可以实现这一功能,并且“一进一出”还符合我们日常生活中对管道的理解

cfc

1、进程进程间通信是有成本的,需要做准备工作:

//2、创建子进程
pid_t id = fork();
if(id == 0)
{//子进程---写端//3、关闭不需要的fdclose(pipefd[0]);close(pipefd[1]);//完成通信后也将子进程的写端关闭exit(0);
}//父进程---读端
close(pipefd[1]);close(pipefd[0]); // 完成通信后也将子进程的读端关闭

2、进程间通信:

#include <iostream>
#include <unistd.h>
#include <cerrno>  //c++版本的errno.h
#include <cstring> //c++版本的string.h
#include <sys/wait.h>
#include <sys/types.h>
#include <string>// 携带发送的信息
std::string getOtherMessage()
{// 获取要返回的信息static int cnt = 0; // 计数器std::string messageid = std::to_string(cnt);cnt++;                    // 每使用一次计数器就++pid_t self_id = getpid(); // 获取当前进程的pidstd::string stringpid = std::to_string(self_id);std::string message = " my messageid is : ";message += messageid;message += " my pid is : ";message += stringpid; // 逐渐向要传回的string字符串中追加要返回的信息return message;
}// 子进程进行写入
void ChildProcessWrite(int wfd)
{std::string message = "father, I am your child process!";while (true){std::string info = message + getOtherMessage(); // 子进程尝试向父进程传递的所有信息write(wfd, info.c_str(), info.size());          // write函数传入的字符串需要是c语言格式的,c_str将string字符串变为c语言格式的字符串sleep(1);                                       // 让子进程写慢一点,这样父进程就不会一直读并打印在显示器上} // write是由操作系统提供的接口,而操作系统又是C语言编写的,所以后续学习中可能会碰到c语言的接口和c++的接口混合使用的情况
} // info最后有/0但是文件不需要const int size = 1024; // 定义父进程可以读取的数组大小// 父进程进行读取
void FatherProcessRead(int rfd)
{char inbuffer[size]; // 普通的c99标准不支持变长数组,但是这里使用的是gnb的c99标准,gun的c99标准支持变长数组while (true){ssize_t n = read(rfd, inbuffer, sizeof(inbuffer)); // 因为文件不需要\0,所以读取管道中内容到缓冲区时可以少读取一个并将/0变为0if (n > 0){inbuffer[n] = 0;std::cout << "父进程获取的消息: " << inbuffer << std::endl;}}
}int main()
{// 1、创建管道int pipefd[2];int n = pipe(pipefd); // 输出型参数,rfd,wfdif (n != 0){std::cerr << "errno" << errno << ":" << "errstring" << strerror(errno) << std::endl;return 1;}// pipefd[0]即读端fd,pipefd[1]即写端fdstd::cout << "pipefd[0] = " << pipefd[0] << ", pipefd[1] = " << pipefd[1] << std::endl;sleep(1); // 便于看到管道创建成功// 2、创建子进程pid_t id = fork();if (id == 0){std::cout << "子进程关闭不需要的fd,准备发消息了" << std::endl;sleep(1); // 便于感受到发消息的过程// 子进程---写端// 3、关闭不需要的fdclose(pipefd[0]);ChildProcessWrite(pipefd[1]); // 子进程的写函数close(pipefd[1]); // 完成通信后也将子进程的写端关闭exit(0);}std::cout << "发进程关闭不需要的fd,准备收消息了" << std::endl;sleep(1); // 便于感受到收消息的过程// 父进程---读端close(pipefd[1]);FatherProcessRead(pipefd[0]); // 父进程的读函数close(pipefd[0]);             // 完成通信后也将子进程的读端关闭pid_t rid = waitpid(id, nullptr, 0);if (rid > 0){std::cout << "wait child process done" << std::endl;}return 0;
}

结论:因为可以用write和read读取管道,所以管道也是文件

管道的四种情况

1、如果管道内部为空,不具备读取条件,读进程会被阻塞(wait)等到管道不为空时才会读取

2、管道被写满 && rfd不关闭也不读取:此时管道会被写满,写进程会被阻塞,等到管道不为满时才会继续写入

3、管道一直在读 && wfd关闭:读端read函数的返回值最后为0,表示读取到了文件结尾

4、rfd直接关闭 && 写端一直入:写端进程会被OS直接用13号信号杀掉(OS判断出进程异常)

管道的五种特征

1、对于匿名管道:只能用来进行具有“血缘关系”的进程间的通信,但常用于父子进程间通信

2、管道内部自带进程之间的同步机制(子进程写一条写父进程读一条(但也不绝对),管道在实现时内部做了保护,不会出现多进程同时访问共享资源导致的共享区数据不一致问题)

3、管道文件按的生命周期是随进程的

4、管道文件在通信的时候,是面向字节流的,读写次数不一定是一一匹配的(写十次一次一条,读一次一次读十条,水管一直流,但是可以选用不同的容器去接水)

5、管道的通信模式,是一种特殊的半双工模式(正常的半双工是双方都写入和接收,但同时只能有一个人写入另一个人负责接收,管道是永远只能有一个人进行写入另一个人进行接收)

~over~

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

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

相关文章

NLP(12)--语言模型

前言 仅记录学习过程&#xff0c;有问题欢迎讨论 应用-语音识别&#xff1a; 声音的本质是一种波&#xff0c;将波按时间段切分为很多帧&#xff0c;之后进行声学特征提取&#xff0c;每一帧转化为向量。 应用-输入法&#xff1a; 按照语言模型给出概率最高的候选词 语言…

2024年化学材料、清洁能源与生物技术国际学术会议(ICCMCEB2024)

2024年化学材料、清洁能源与生物技术国际学术会议(ICCMCEB2024) 会议简介 2024国际化学材料、清洁能源和生物技术大会&#xff08;ICCMCEB2024&#xff09;将在长沙隆重举行。本次会议旨在汇聚来自世界各地的化学材料、清洁能源和生物技术领域的专家学者&#xff0c;共同探…

用C++译密码

为使电文保密&#xff0c;往往按一定规律将电文转换成密码&#xff0c;收报人再按约定的规律将其译回原文。例如&#xff0c;可以按以下规律将电文变成密码&#xff1a;将字母A变成字母E,a变成e&#xff0c;即变成其后的第4个字母&#xff0c;W变成A,X变成B,Y变成C,Z变成D。字母…

【吃透Java手写】3-SpringBoot-简易版-源码解析

【吃透Java手写】SpringBoot-简易版-源码解析 1 SpringbootDemo2 准备工作2.1 Springboot-my2.1.1 依赖2.1.2 SpringBootApplication2.1.3 SJBSpringApplication2.1.3.1 run方法 2.2 Springboot-user2.2.1 依赖2.2.2 UserController2.2.3 UserApplication 2.3 分析run方法的逻辑…

Vue+OpenLayers7入门到实战:OpenLayers实现鼠标拖拽方式绘制矩形(正方形和长方形)

返回《Vue+OpenLayers7》专栏目录:Vue+OpenLayers7入门到实战 前言 本章介绍如何使用OpenLayers7在地图上实现鼠标拖拽方式绘制矩形(拖拽方式长方形和正方形)。 OpenLayers本身是可以通过鼠标点击多个点的方式来绘制多边形的,当然也包括长方形和正方形,但是这种多边形绘…

Ollama + Openwebui 本地部署大型模型与交互式可视化聊天

Ollama简介 Ollama是一个创新的平台&#xff0c;它允许用户在本地启动并运行大型语言模型。它提供了一个简单易用的内容生成接口&#xff0c;类似于OpenAI&#xff0c;但无需开发经验即可直接与模型进行交互。Ollama支持热切换模型&#xff0c;为用户提供了灵活性和多样性。 …

港股开启估值修复行情 珠光效果材料龙头大涨25%

进入二季度以来&#xff0c;港股市场持续大涨&#xff0c;仅4月恒生指数就大涨7.4%&#xff0c;5月涨幅继续扩大至12.31%&#xff0c;大幅跑赢全球各主要指数。尤其是随着恒生科技多年以来的估值底部的确认&#xff0c;至此恒生指数、恒生港股通&#xff0c;恒生高股息&#xf…

使用C语言实现杨氏矩阵并找出数字

前言 过了五一假期&#xff0c;咋们经过了一个假期的休息&#xff0c;要继续学习了&#xff0c;不能偷懒哦&#xff01;&#xff01; 今天让我们来看看如何在一个杨氏矩阵中找出自己想找到的数字。 首先&#xff0c;我们要了解一下杨氏矩阵到底是什么&#xff0c;如果一个矩阵中…

概念解析 | ROC曲线:评估分类模型

注1:本文系"概念解析"系列之一,致力于简洁清晰地解释、辨析复杂而专业的概念。本次辨析的概念是:ROC曲线的含义和绘制 概念解析 | ROC曲线:评估分类模型 第一部分:通俗解释 在我们的日常生活中,经常会遇到需要做出判断和选择的情况。比如,当你收到一封邮件时…

深度学习(算法工程师)最火的就业方向

自动驾驶与智能交通 自动驾驶是深度学习技术的一个重要应用领域&#xff0c;其目标是实现车辆的自主导航和驾驶。自动驾驶系统需要借助深度学习技术来识别交通信号、行人、车辆等环境信息&#xff0c;并做出相应的决策。因此&#xff0c;自动驾驶与智能交通领域的就业方向包括…

WPS二次开发系列:一文快速了解WPS SDK功能场景

作者持续关注 WPS二次开发专题系列&#xff0c;持续为大家带来更多有价值的WPS开发技术细节&#xff0c;如果能够帮助到您&#xff0c;请帮忙来个一键三连&#xff0c;更多问题请联系我&#xff08;QQ:250325397&#xff09; 目录 SDK功能介绍 功能详解&#xff1a; 打开文档…

第十二届蓝桥杯省赛真题 Java B 组【原卷】

文章目录 发现宝藏【考生须知】试题 A: ASC试题 B : 卡片试题 C: 直线试题 D: 货物摆放试题 E: 路径试题 F: 时间显示试题 G: 最少砝码试题 H: 杨辉三角形试题 I: 双向排序试题 J: 括号序列 发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;…

echarts指标盘属性概括

echarts指标盘属性概括 代码 有模拟数据可以直接使用const options {animation: true,title: {top: "35%",left: "center",// text: "单元测试覆盖度", // 主标题itemGap: 15,textStyle: {// 主标题样式color: "#666666",fontSize:…

YOLOv5改进 | 独家创新篇 | 利用MobileNetV4的UIB模块二次创新C3(全网独家首发)

一、本文介绍 本文给大家带来的改进机制是利用MobileNetV4的UIB模块二次创新C3&#xff0c;其中UIB模块来自2024.5月发布的MobileNetV4网络&#xff0c;其是一种高度优化的神经网络架构&#xff0c;专为移动设备设计。它最新的改动总结主要有两点&#xff0c;采用了通用反向瓶…

微同城小程序源码 轻松制作本地生活活动赚钱 带完整的安装代码包以及搭建教程

近年来&#xff0c;本地生活服务市场蓬勃发展&#xff0c;人们对于周边的生活信息、活动资讯等需求日益增长。然而&#xff0c;传统的信息发布方式存在诸多不便&#xff0c;如信息更新不及时、传播范围有限等。微同城小程序源码应运而生。它利用小程序的便捷性和普及性&#xf…

海睿思受邀参加 “走进中节能”研习交流,探索新能源数据治理的创新路径

近日&#xff0c;OceanMind海睿思参加由江苏省企业信息化协会&#xff08;以下简称“苏信会”&#xff09;主办的“走进中节能太阳能科技&#xff08;镇江&#xff09;有限公司”研习交流活动。 海睿思与苏美达、远东控股、隆基乐叶、固德威、上能电气等40多位来自制造业领域的…

04-25 周四 FastBuild重构实践-TLS、全局捕获异常、一键配置

04-25 周四 FastBuild重构实践 时间版本修改人描述04-25V0.1宋全恒新建文档2024年5月6日14:33:16V1.0宋全恒完成文档撰写 简介 由于 04-22 周日 阿里云-瑶光上部署FastBuild过程(配置TLS、自定义辅助命令)描述了重新部署一个FastBuild实例的过程&#xff0c;通过阅读这个&…

怎么设置付费视频课程_在线教育知识付费系统

在信息爆炸的时代&#xff0c;我们每天都被海量的信息包围。然而&#xff0c;真正有价值、能够让我们快速提升的知识&#xff0c;往往隐藏在这些信息的深海之中。今天&#xff0c;我要为大家介绍的&#xff0c;就是这样一份珍贵的宝藏——我们的付费视频课程。 工具/原料 微信…

手把手教你微调Stable Diffusion

温馨提示 关于本文&#xff1a; 本文你可以学习到完整的不使用webui借助lora和dreambooth微调Stable Diffusion的全过程。 手把手教你微调Stable Diffusion生成优弧&#xff0c;但是半失败版&#x1f602; 关于训练&#xff1a; 单卡32GV100进行的微调&#xff0c;因为一些…

【leetcode】数学位数题总结

涉及题型&#xff1a;两数相加问题、大数溢出等 相加问题 根据题意定义rs的数据结构判断是存储方式是正序还是逆序&#xff0c;如果是正序需要反转 比如 123 12 135是正序&#xff0c; 321 21 135是逆序反转的方式&#xff1a;对于可以从后往前遍历的&#xff08;如字符串…