当前位置: 首页 > article >正文

Linux——进程通信

我们知道,进程具有独立性,各进程之间互不干扰,但我们为什么还要让其联系,建立通信呢?比如:数据传输,资源共享,通知某个事件,或控制某个进程。因此,让进程间建立通信是必不可少的。但如何通信呢?

根据进程的独立性,我们需要保证,让不同的进程看到同一份资源!但这个资源若是进程a建立的则b看不到,b建立的a看不到,因此,这份资源必须由操作系统提供!

   进程间通信分类

      一、.管道

管道在Linux中算是比较古老经典的一种通信方式

假设我们现在有一个进程(PCB,内存 mm_struct等结构),同时其有一个文件描述符表,对应了 某个正在加载的文件(文件在加载就有对应的struct _file、inode),现在我让进程fork出一个子进程,那么PCB等结构会以父进程为模板进行拷贝。但是内核缓冲区、inode也会拷贝吗?不会!文件只会被加载一次,(但struct_file会拷贝,子进程需要有自己的读写位置)那么这个文件是父子进程的共享资源。那么如果我们让父子进程中一方对文件进行写,一方进行读,不就形成了进程间通信了吗?这个以文件方式进行通信的方式我们称为管道。

实际上,两个进程的共享资源是文件内核缓冲区,而且,要让两个进程间通信,就没必要把数据刷新到磁盘。我们用一张图解释一下管道的原理

从图里我们也能看出,管道只能进行单向通信。

我们概念解释一下就是,从一个进程连接到另一个进程的一个数据流。

2.管道创建的接口

如果创建成功就返回0,失败返回-1,其中参数是一个输出型参数,输出管道所连的两个文件的fd。

3.按顺序创建一下管道

#include <iostream>
#include <string>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>// 让父进程写
// 让子进程读
int main()
{// 1. 创建管道int fds[2] = {0};int n = pipe(fds); // fds:输出型参数if (n != 0){//创建管道失败了std::cerr << "pipe error" << std::endl;return 1;}// Father -> read// Child  -> write// 2. 创建子进程pid_t id = fork();if (id < 0){std::cerr << "fork error" << std::endl;return 2;}else if (id == 0){// 子进程// 3. 关闭不需要的fd,关闭readclose(fds[0]);int cnt = 0;while (true){std::string message = "hello";message += std::to_string(getpid());message += ", ";message += std::to_string(cnt);// fds[1]write(fds[1],message.c_str,message.size());cnt++;sleep(1);// break;}exit(0);}else{// 父进程// 3. 关闭不需要的fd,关闭writeclose(fds[1]);char buffer[1024];while (true){sleep(1);ssize_t n = read(fds[0], buffer, 1024);if (n > 0){buffer[n] = 0;std::cout << "child->father, message: " << buffer << std::endl;}else if(n == 0) {}close(fds[0]);break;std::cout << std::endl;}}return 0;
}

我们想让子进程写就需要把读的接口关闭,同理就需要关闭父进程的写入接口。而通常我们的fds[0]表示读,fds[1]表示写。我们这里实现让子进程向文件写入,然后让父进程读取。

3.管道的一些情况

在管道正常的情况下,如果管道为空,那么read会阻塞,如果管道写满了,write会阻塞,其中并不会出现在写入的过程中去读,也不会在读的过程中进行写,这种保护机制在管道本身就已经形成。如果管道写端关闭(比如子进程写入后退出),读端继续,知道读到0表示读到文件结尾。如果管道写端正常,读端关闭,操作系统会直接杀掉写入的进程(此时的写入已经没有意义)

4.管道的特性

我们以上说的管道的相关问题都指的是匿名管道。因为创建管道时并没有名称。关于匿名管道我们有以下特性:


可以用来进行具有血缘关系的进程间通信

文件的生命周期随进程终止而终止,管道也是

只能做到单向数据通信

管道自带同步互斥等保护机制(读写有相对顺序)

二、管道通信的具体场景——进程池

我们刚才说到,如果管道为空,那么read方就会阻塞,知道有人写入才会读,假设有一个父进程fork出好几个子进程,此时其又为每一个子进程建立了管道,但此时在管道中没有内容,那么作为子进程就只能阻塞,等到父进程进行写入后进行通信。此时如果父进程向管道中写入某些命令,并让子进程们去执行,那么我们就可以像分派任务一样完成操作。像这样的模型我们称为进程池。

三、命名管道

上面我们的所有管道都是匿名管道,匿名管道没有名字,那么在通信时父子进程时如何看到这个管道的呢?->因为子进程继承了父进程的资源。但如果我想让任意两个进程间进行通信呢?此时就需要对管道进行命名了。

创建命名管道:

mkfifo name

我们来用一下,此时我们写入命令:echo "hello">fifo。我们发现卡住了,我们再启动一个终端并写入"cat <fifo"我们发现两个终端恢复正常并打印hello。相当于把内容写在管道然后等待另一端进行读,这就是基本的通信流程。

1.为什么叫命名管道

我们查看管道的详细信息发现,它是一个文件,有自己的inode,文件类型以p开头,也就是说它也有唯一的路径和文件名。这样我们可以用同一个文件系统路径,让两个进程看到同一份进程进行通信。其原理就是让操作系统只使用内核文件缓冲区,只是不刷新就可以了。

我们还有用函数来创建命名管道的方式:

第一个参数就是创建管道的路径,第二个参数是权限。创建成功返回0,出错返回-1

四、system V共享内存

我们知道,一个进程有自己的虚拟地址空间,然后通过页表映射到真实的物理地址,在虚拟地址空间中,有一块共享区,前面我们提到过,一般会把动态库映射到此部分,但现在如果我们在物理内存上开辟一块空间,然后让其通过页表映射到共享区,同样地,另一个进程也进行此操作,那么最终就会形成一个物理地址对应两个虚拟地址,就成功让两个进程看到同一份资源了。这就是共享内存。

共享内存可以在任何时刻在OS内存在多个。

创建共享内存的接口:shmget

第三个参数是一个标记位,我们常用的有IPC_CREAT和IPC_EXCL(宏),前者的作用是,如果内存不存在则创建,如果存在,将其获取并返回。对于后者,如果单独使用无意义,一般二者组合使用(|)。表示,如果内存不存在则创建,如果存在,出错返回。

返回值是一个shmid(共享内存标识符),可以看成数组下标,但和文件描述符相比,这个下标可以从0开始。失败返回-1.

第一个参数必须由用户手动输入,这个参数是用来保证两个进程所映射的是同一份内存,因为我们往往会有很多对共享内存同时存在,为了保证不出错,我们需要让每一份内存都具有唯一性,我们就可以用这个参数进行编号(具体输入由用户决定,能体现唯一性即可),这样我们就可以通过路径+id即可保证映射同一份资源。同时,系统中也有用来生成key值对应的函数:key_t ftok(路径,projid)

共享内存生命周期随内核!

已经开辟的共享内存要么手动释放,要么让OS重启。

五、共享内存的管理指令

1.查看已经开辟的共享内存——ipcs -m

2.删除共享内存——ipcrm -m shmid

3.控制共享内存的相关属性——shmctl函数 

第二个参数我们传对应的宏选项即可,第三个参数用于获取共享内存的相关属性,一般置为nullptr。

比如我们可以用函数删除共享内存

shmctl( shmid,IPC_RMID,nullptr);

六、共享内存的特点 

1.通信速度最快,相比于管道,共享内存只需要一次拷贝,提高了效率。

2.可以让两个进程在各自的用户空间共享内存块,但是没有加任何保护机制!

3.这个保护机制需要由用户自己完成,其中,共享资源被保护起来的话就称临界资源,而我们的代码并不完全都是访问共享内存的,只有访问公共资源的代码我们称临界区,对应的就是非临界区  

相关文章:

Linux——进程通信

我们知道&#xff0c;进程具有独立性&#xff0c;各进程之间互不干扰&#xff0c;但我们为什么还要让其联系&#xff0c;建立通信呢&#xff1f;比如&#xff1a;数据传输&#xff0c;资源共享&#xff0c;通知某个事件&#xff0c;或控制某个进程。因此&#xff0c;让进程间建…...

学习笔记十三—— 理解 Rust 闭包:从语法到 impl Fn vs Box<dyn Fn>

&#x1f9e0; 理解 Rust 闭包&#xff1a;从语法到 impl Fn vs Box &#x1f4da; 目录 闭包是什么&#xff1f;和普通函数有什么不同&#xff1f;闭包的语法长什么样&#xff1f;闭包“捕获变量”是什么意思&#xff1f;闭包和所有权的关系Fn、FnMut、FnOnce 三种闭包类型的…...

【免费参会合集】2025年生物制药行业展会会议表格整理

全文精心整理, 建议今年参会前都好好收藏着&#xff0c;记得点赞&#xff01; 医药人非常吃资源&#xff0c;资源从何而来&#xff1f;作为一名从事医药行业的工作者&#xff0c;可以很负责任的告诉诸位&#xff0c;其中非常重要的一个渠道就是会议会展&#xff01; 建议所有医…...

腾讯云开发+MCP:旅游规划攻略

1.登录注册好之后进入腾讯云开发 2.创建环境 4.创建好环境之后点击去开发 5.进入控制台后&#xff0c;选择AI&#xff0c;找到MCP 6.点击创建MCP Server 使用腾讯云开发创建MCP目前需要云开发入门版99/月&#xff0c;我没开通&#xff0c;所以没办法往下进行。...

银河麒麟系统 达梦8 安装 dlask 框架后端环境

适配的一套环境为 dmPython2.5.8 dmSQLAlchemy1.4.39 Flask2.0.3 Flask-Cors3.0.10 Flask-SQLAlchemy2.5.1 SQLAlchemy1.4.54 Werkzeug2.2.2其中 # sqlalchemy-dm1.4.39 通过dmdbms目录内文件进行源码安装 (MindSpore) [ma-user python]$pwd /home/syl/dmdbms/drivers/python…...

Cribl (实验) vpc-flow 数据抽样

先看文档: Firewall Logs: VPC Flow Logs, Cisco ASA, Etc. | Cribl Docs Firewall Logs: VPC Flow Logs, Cisco ASA, Etc. Recipe for Sampling Firewall Logs Firewall logs are another source of important operational (and security) data. Typical examples include Ama…...

Sklearn入门之数据预处理preprocessing

、 Sklearn全称:Scipy-toolkit Learn是 一个基于scipy实现的的开源机器学习库。它提供了大量的算法和工具&#xff0c;用于数据挖掘和数据分析&#xff0c;包括分类、回归、聚类等多种任务。本文我将带你了解并入门Sklearn下的preprocessing在机器学习中的基本用法。 获取方式…...

我想自己组装一台服务器,微调大模型通义千问2.5 Omni 72B,但是我是个人购买,资金非常有限,最省的方案

目录 🧠 首先我们要搞清楚几个核心点: 🎯 目标:微调 Qwen2.5-Omni-72B 🚨 现实问题:作为个人用户,72B 模型几乎无法负担全量微调 💸 全量微调硬件需求: ✅ 最省的个人方案:不组 72B,只训练 Qwen2.5-Omni-7B 或 14B 💡 推荐方案 A:个人桌面级多卡训练服…...

家用打印机性价比排名及推荐

文章目录 品牌性价比一、核心参数对比与场景适配二、技术类型深度解析三、不同场景选择 相关文章 品牌 性价比 一、核心参数对比与场景适配 兄弟T436W 优势&#xff1a; 微压电技术&#xff0c;打印头寿命长&#xff0c;堵头率低。 支持A4无边距和5G WiFi&#xff0c;适合照片…...

KWDB(Knowledge Worker Database)基础概念与原理完整指南

KWDB&#xff08;Knowledge Worker Database&#xff09;基础概念与原理完整指南—目录 前言一、背景1.1 知识工作者的痛点1.2 技术演进推动 二、定义与定位2.1 什么是KWDB&#xff1f;2.2 KWDB与传统数据库的对比与传统关系型数据库&#xff08;如MySQL&#xff09;的对比与分…...

数字电子技术基础(四十七)——使用Mutlisim软件来模拟74LS85芯片

目录 1 使用74LS85N芯片完成四位二进制数的比较 1.1原理介绍 1.2 器件选择 1.3 运行电路 2 使用74LS85N完成更多位的二进制比较 1 使用74LS85N芯片完成四位二进制数的比较 1.1原理介绍 对于74LS85 是一款 4 位数值比较器集成电路&#xff0c;用于比较两个 4 位二进制数&…...

关于STM32创建工程文件启动文件选择

注意启动文件只要选择这几个 而不是要把所有都选上...

LLC电路工作在容性区的风险

在t0时刻之前&#xff0c;Q6Q7导通&#xff0c;回路如下所示&#xff0c;此时A点电压是低压&#xff0c;B点电压是高压 在t0时刻时&#xff0c;谐振电流相位发生变换&#xff0c;在t1时刻&#xff0c;Q5&#xff0c;Q8导通&#xff0c;对于Q8MOS管来说&#xff0c;B点电压在Q6Q…...

Linux Kernel 6

clone 系统调用&#xff08;The clone system call&#xff09; 在 Linux 中&#xff0c;使用 clone() 系统调用来创建新的线程或进程。fork() 系统调用和 pthread_create() 函数都基于 clone() 的实现。 clone() 系统调用允许调用者决定哪些资源应该与父进程共享&#xff0c…...

【开源项目】Excel手撕AI算法深入理解(四):AlphaFold、Autoencoder

项目源码地址&#xff1a;https://github.com/ImagineAILab/ai-by-hand-excel.git 一、AlphaFold AlphaFold 是 DeepMind 开发的突破性 AI 算法&#xff0c;用于预测蛋白质的三维结构。它的出现解决了生物学领域长达 50 年的“蛋白质折叠问题”&#xff0c;被《科学》杂志评为…...

第IV部分有效应用程序的设计模式

第IV部分有效应用程序的设计模式 第IV部分有效应用程序的设计模式第23章:应用程序用户界面的架构设计23.1设计考量23.2示例1:用于非分布式有界上下文的一个基于HTMLAF的、服务器端的UI23.3示例2:用于分布式有界上下文的一个基于数据API的客户端UI23.4要点第24章:CQRS:一种…...

如何编制实施项目管理章程

本文档概述了一个项目管理系统的实施计划,旨在通过统一的业务规范和技术架构,加强集团公司的业务管控,并规范业务管理。系统建设将遵循集团统一模板,确保各单位项目系统建设的标准化和一致性。 实施范围涵盖投资管理、立项管理、设计管理、进度管理等多个方面,支持项目全生…...

排序(java)

一.概念 排序&#xff1a;对一组数据进行从小到大/从大到小的排序 稳定性&#xff1a;即使进行排序相对位置也不受影响如&#xff1a; 如果再排序后 L 在 i 的前面则稳定性差&#xff0c;像图中这样就是稳定性好。 二.常见的排序 三.常见算法的实现 1.插入排序 1.1 直…...

嵌入式C语言进阶(二+)内存管理补充版

C语言内存管理:从小白到大神的完全指南 前言:为什么需要理解内存管理 C语言以其高效性和灵活性著称,但这也意味着程序员需要手动管理内存。与Java、Python等高级语言不同,C语言没有自动垃圾回收机制,内存管理的重担完全落在开发者肩上。理解C语言的内存管理机制不仅能帮…...

【HDFS入门】HDFS副本策略:深入浅出副本机制

目录 1 HDFS副本机制概述 2 HDFS副本放置策略 3 副本策略的优势 4 副本因子配置 5 副本管理流程 6 最佳实践与调优 7 总结 1 HDFS副本机制概述 Hadoop分布式文件系统(HDFS)的核心设计原则之一就是通过数据冗余来保证可靠性&#xff0c;而这一功能正是通过副本策略实现的…...

Excel自定义函数取拼音首字母

1.启动Excel 2003&#xff08;其它版本请仿照操作&#xff09;&#xff0c;打开相应的工作表&#xff1b; 2.执行“工具 > 宏 > Visual Basic编辑器”命令&#xff08;或者直接按“AltF11”组合键&#xff09;&#xff0c;进入Visual Basic编辑状态&#xff1b; 3.执行“…...

智能 GitHub Copilot 副驾驶® 更新升级!

智能 GitHub Copilot 副驾驶 迎来重大升级&#xff01;现在&#xff0c;所有 VS Code 用户都能体验支持 Multi-Context Protocol&#xff08;MCP&#xff09;的全新 Agent Mode。此外&#xff0c;微软还推出了智能 GitHub Copilot 副驾驶 Pro 订阅计划&#xff0c;提供更强大的…...

Android ViewPager使用预加载机制导致出现页面穿透问题

​ 缘由 在应用中使用ViewPager&#xff0c;并且设置预加载页面。结果出现了一些异常的现象。 我们有4个页面&#xff0c;分别是4个Fragment&#xff0c;暂且称为FragmentA、FragmentB、FragmentC、FragmentD&#xff0c;ViewPager在MainActivity中&#xff0c;切换时&#x…...

【今日三题】添加字符(暴力枚举) / 数组变换(位运算) / 装箱问题(01背包)

⭐️个人主页&#xff1a;小羊 ⭐️所属专栏&#xff1a;每日两三题 很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~ 目录 添加字符(暴力枚举)数组变换(位运算)装箱问题(01背包) 添加字符(暴力枚举) 添加字符 当在A的开头或结尾添加字符直到和B长度…...

【AIoT】智能硬件GPIO通信详解(二)

前言 上一篇我们深入解析了智能硬件GPIO通信原理(传送门:【AIoT】智能硬件GPIO通信详解(一))。接下来,我们将结合无人售货机控制场景,通过具体案例进一步剖析物联网底层通信机制的实际应用。 在智能零售领域,无人售货机通过AI技术升级为智能柜,其设备控制的底层通信…...

Python(18)Python中JSON的妙用:详解序列化与反序列化原理及实战案例

目录 一、背景&#xff1a;为什么Python需要JSON&#xff1f;二、核心技术解析&#xff1a;序列化与反序列化2.1 核心概念2.2 类型映射对照表 三、Python操作JSON的四大核心方法3.1 基础方法库3.2 方法详解1. json.dumps()2. json.loads()3. json.dump()4. json.load() 四、实战…...

【Python进阶】字典:高效键值存储的十大核心应用

目录 前言&#xff1a;技术背景与价值当前技术痛点解决方案概述目标读者说明 一、技术原理剖析核心概念图解核心作用讲解关键技术模块技术选型对比 二、实战演示环境配置要求核心代码实现&#xff08;10个案例&#xff09;案例1&#xff1a;基础操作案例2&#xff1a;字典推导式…...

MATLAB脚本实现了一个三自由度的通用航空运载器(CAV-H)的轨迹仿真,主要用于模拟升力体在不同飞行阶段(初始滑翔段、滑翔段、下压段)的运动轨迹

%升力体:通用航空运载器CAV-H %读取数据1 升力系数 alpha = [10 15 20]; Ma = [3.5 5 8 10 15 20 23]; alpha1 = 10:0.1:20; Ma1 = 3.5:0.1:23; [Ma1, alpha1] = meshgrid(Ma1, alpha1); CL = readmatrix(simulation.xlsx, Sheet, Sheet1, Range, B2:H4); CL1 = interp2(…...

多角度分析Vue3 nextTick() 函数

nextTick() 是 Vue 3 中的一个核心函数&#xff0c;它的作用是延迟执行某些操作&#xff0c;直到下一次 DOM 更新循环结束之后再执行。这个函数常用于在 Vue 更新 DOM 后立即获取更新后的 DOM 状态&#xff0c;或者在组件渲染完成后执行某些操作。 官方的解释是&#xff0c;当…...

Linux——消息队列

目录 一、消息队列的定义 二、相关函数 2.1 msgget 函数 2.2 msgsnd 函数 2.3 msgrcv 函数 2.4 msgctl 函数 三、消息队列的操作 3.1 创建消息队列 3.2 获取消息队列并发送消息 3.3 从消息队列接收消息recv 四、 删除消息队列 4.1 ipcrm 4.2 msgctl函数 一、消息…...