进程间通信 管道

前言

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.rhkb.cn/news/323592.html

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

相关文章

PG的事务ID回卷逻辑

PG到目前为止使用的事务ID仍然是32位的&#xff0c;在内存计算时虽然已经使用64位事务ID&#xff0c;但是存储在页中tuple仍然使用32位事务ID&#xff0c;这就是说&#xff0c;事务ID回卷仍然是必须处理的问题。 所谓PG事务ID回卷&#xff0c;简单地说&#xff0c;就是在数据库…

基于FPGA实现的HDMI TO MIPI扩展显示器方案

FPGA方案&#xff0c;HDMI IN接收原始HDMI 信号&#xff0c;输出显示到LCD 屏上 客户应用&#xff1a;扩展显示器 主要特性&#xff1a; 1.支持2K以下任意分辨率显示 2.支持OSD 叠加多个图层 3.支持MIPI/EDP/LVDS/RGB屏 4.支持放大缩小匹配屏分辨率 5.零延时&#xff0c;输…

【vue-echarts】 报错问题解决 “Error: Component series.pie not exists. Load it first.“

目录 问题描述解决【解决1】【解决2】 问题描述 使用 vue-echarts 时导入的文件 import VChart from vue-echarts/components/ECharts import echarts/lib/chart/line import echarts/lib/chart/bar import echarts/lib/chart/pie import echarts/lib/component/legend impor…

文心一言 VS 讯飞星火 VS chatgpt (255)-- 算法导论18.3 1题

一、请说明依次从图18-8(f)中删除C、P和V后的结果。如果要写代码&#xff0c;请用go语言。 文心一言&#xff1a; 首先&#xff0c;让我们明确一点&#xff1a;由于您没有提供具体的图18-8(f)的内容&#xff0c;我只能假设它是一个数据结构&#xff08;可能是图、树或列表等&…

Wireshark下载安装和使用教程

Wireshark下载安装和使用教程 Wireshark&#xff08;前身 Ethereal&#xff09;是一个网络包分析工具。该工具主要是用来捕获网络数据包&#xff0c;并自动解析数据包&#xff0c;为用户显示数据包的详细信息&#xff0c;供用户对数据包进行分析。 它可以运行在 Windows 和 L…

JavaScript初了解

JS的三种书写位置&#xff1a;行内&#xff0c;内嵌&#xff0c;外部 JS的注释的书写&#xff1a;单行注释&#xff1a;// ctrl/ 多行注释&#xff1a;/**/ ShiftAltA JavaScript输入输出语句

【Java orm 框架比较】九 新增wood框架对比

【Java orm 框架比较】九 新增wood框架对比 本次新增wood 框架测试 测试数据存储、分页查询&#xff0c;文档及框架比较稳定半天时间加入测试使用 迁移到&#xff08;https://gitee.com/wujiawei1207537021/spring-orm-integration-compare&#xff09; orm框架使用性能比较…

Linux环境下部署vsftp+mysql用户认证

安装mysql(不要使用红帽的RPM版的mysql) 使用编译或静态库安装mysql 1、编译安装pam_mysql 下载软件&#xff1a; http://downloads.sourceforge.net/project/pam-mysql/pam-mysql/0.7RC1/pam_mysql-0.7RC1.tar.gz?rhttp%3A%2F%2Fsourceforge.net%2Fprojects%2Fpam-mysql%2F…

Verilog复习(三)| Verilog语言基础

四种基本的逻辑值 0&#xff1a;逻辑0或“假”1&#xff1a;逻辑1或“真”x&#xff1a;未知z&#xff1a;高阻 三类常量 整型数&#xff1a;简单的十进制格式&#xff0c;基数格式&#xff08;5’O37&#xff0c;4’B1x_01&#xff09; 格式&#xff1a; <size><’b…

Spring Gateway的核心功能:路由、过滤、限流一网打尽

Spring Gateway的简介 在微服务架构的世界里&#xff0c;如同繁星点点的服务需要一个指挥家&#xff0c;将它们有序地组织起来&#xff0c;让它们能够和谐地协同工作。这个指挥家&#xff0c;就是Spring Gateway。它是一个基于Spring Framework 5、Project Reactor和Spring Bo…

AI 资料汇总专栏

包含AI资料、大模型资料、AI最新行业发展 人工智能&#xff08;Artificial Intelligence&#xff0c;简称AI&#xff09;是一门研究如何使计算机能够具备智能行为的科学与技术。它致力于开发出能够像人类一样思考、学习、理解和决策的计算机系统。自20世纪50年代以来&#xff…

Spring与AI结合-spring boot3整合AI组件

⛰️个人主页: 蒾酒 &#x1f525;系列专栏&#xff1a;《spring boot实战》 目录 写在前面 spring ai简介 单独整合al接口 整合Spring AI组件 起步条件 ​编辑 进行必要配置 写在最后 写在前面 本文介绍了springboot开发后端服务中&#xff0c;AI组件(Spring A…

学生管理系统初级

根据题目要求生成大纲 总结: 1.在书写时&#xff0c;考虑到了书写时id可是是abc... 类型是String&#xff0c;但在根据id获取集合中元素时 list.get() &#xff0c;get&#xff08;&#xff09;里面是int类型。 2.在书写还有一点功能并不完全&#xff0c; 2.1查找时是打印所有…

软件系统安全设计规范(word原件)

1.1安全建设原则 1.2 安全管理体系 1.3 安全管理规范 1.4 数据安全保障措施 1.4.1 数据库安全保障 1.4.2 操作系统安全保障 1.4.3 病毒防治 1.5安全保障措施 1.5.1实名认证保障 1.5.2 接口安全保障 1.5.3 加密传输保障 1.5.4终端安全保障 软件资料清单列表部分文档…

SpringCloud 集成consul,消费者报I/O error on GET request for...

创建消费者微服务&#xff0c;去调用生产者微服务的请求过程中&#xff0c;出现以下错误&#xff1a; 报错原因 因为在使用SpringCloudAlibaba中的Nacos框架时&#xff0c;自动整合了SpringCloud中的Ribbon框架中的负载均衡&#xff0c;因为微服务提供者有两个&#xff0c;在消…

使用apache和htaccess对目录访问设置密码保护配置教程

对目录设置密码保护配置说明 我们有时候访问某些网站的时候&#xff0c;要求输入用户名和密码才能访问。这是为了保护隐私&#xff0c;只让经过许可的人访问。 在本教程中主要介绍两种方法&#xff0c;一种是通过apache httpd.conf配置文件对管理后台目录设置密码保护&#xff…

BS架构 数据权限--字段级权限 设计与实现

一、需求场景 1. 销售发货场景 销售出库单上 有 商品名称、发货数量、单价、总金额 等信息。 销售人员 关注 上述所有信息&#xff0c;但 仓管人员 不需要知道 单价、总金额 信息。 2. 配方、工艺保密 场景 配方研发人员 掌握核心配方&#xff0c; 但 交给车间打样、生产时…

变色龙Ultra:IC、ID卡读+写+模拟的开源项目

虽然已经很多年没用过刷卡的东西了&#xff0c;确实没有破解或者模拟卡片的需求&#xff0c;但是看到这个开源项目的时候&#xff0c;还是觉得有点意思&#xff0c;值得一看。 这是ultra版本的原理框图&#xff0c;可知ultra体现在加了一个射频卡芯片&#xff0c;南京中科微的C…

亚信安慧AntDB新篇章:数据库技术飞跃

随着大数据时代的到来&#xff0c;对数据库的需求愈发强烈。在这一背景下&#xff0c;国产数据库逐渐崭露头角&#xff0c;亚信安慧AntDB作为重要的代表产品之一正积极参与到激烈的市场竞争中。亚信安慧AntDB不仅追求技术的革新和突破&#xff0c;同时也致力于满足用户日益增长…

JavaWeb中的Session和Cookie

前言 什么是会话跟踪技术 Cookie 1.什么是cookie 2.Cookie的应用 2.1 保持用户登录状态 2.2 记录用户名 3. Cookie的设置和获取 3.1 、通过HttpServletResponse.addCookie的方式设置Cookie 3.2、浏览器中查看cookie的内容 3.3、服务端获取客户端携带的cookie&#xf…