【操作系统笔记十一】进程间通信
Linux文件系统
inode 节点 (index node):给每个文件赋予一个称为 i 节点的数据结构。
inode 一开始是存储在硬盘中的,只有当文件被打开的时候,其对应的 i 节点才加载到内存中。
总结:
-
Linux 中,用户态通过读写文件的 Api 进行系统调用,在内核态中,上层是虚拟文件操作系统 VFS,它为用户态提供统一接口,屏蔽底层实现细节,VFS 层定义了底层具体的文件系统需要实现的接口,VFS 层往下对接不同的具体的文件系统如 ext4,具体的文件系统再去操作磁盘的文件块信息
-
Linux 中每个文件对应一个称为
iNode
的数据结构,inode
中包含了文件的元数据以及若干的块地址信息,inode
一开始存储在磁盘中,当文件被打开时,inode
节点会被加载到内存当中 -
每个进程的
task_struct
中包含files_struct
结构体,files_struct
中又包含一个fd
数组fd_array
,fd_array
中则包含对应文件的文件操作符file
,file
文件操作符是通过inode
去读写文件的,inode
中定义了inode_options
,而具体的底层文件系统则实现了inode_options
中定义的对应读写接口的具体方法
管道
Linux 进程间通信方式:管道、共享内存、信号量、消息队列
① 匿名管道
② 命名管道
管道的实现
一个文件可以同时被多个进程访问
所以,我们可以使用文件来实现进程间的通信,管道就是基于文件系统来实现的。
实现进程和其子进程之间的管道通信
父进程在复制子进程时,会把父进程的相关信息全部拷贝过来,其中就包括file_struct
结构体,而这个结构体中就包含了文件读写inode
的两个文件描述符,一个 file_0
只读, 一个 file_1
只写,由于是复制的,所以父子进程的这俩文件描述符是指向的同一个文件的inode
。
此时把父进程的 file_0
只读文件描述符 close 掉,把子进程的 file_1
只写文件描述符 close 掉,父进程只保留只写文件描述符,子进程只保留只读文件描述符,这样父进程就可以和子进程通信了(父进程只写,子进程只读,半双工)。
匿名管道的实现
匿名管道底层实现:
匿名管道通过虚拟文件系统 VFS 调用底层的 pipefs 内存文件系统,也就是说底层实现是基于 pipefs 文件系统的。
pipefs 文件系统的数据结构:https://www.processon.com/view/link/62822757e401fd36f6bcc5dd
管道在内存中的实现本质就是一段内核 buffer 内存,不同的文件操作符(一个读一个写)对这段 buffer 进行读写操作。
关于 ps -ef | grep systemd 命令背后的匿名管道的底层实现数据结构:
命名管道底层实现流程图:
总结
-
管道是基于文件系统来实现的,也就是多个进程对同一个文件进行读写来实现进程间通信
-
进程和子进程之间的管道通信:父进程在
fork
子进程时,会把父进程相关信息全部拷贝过来,其中包括file_struct
结构体,file_struct
中包含了文件读写inode
的两个文件描述符,一个file_0
只读,一个file_1
只写,由于是复制的,所以父子文件的这俩文件描述符是指向同一个文件的inode
, 此时把父进程的file_0
只读 fd 关闭掉,然后再把子进程的file_1
只写 fd 关闭掉,父进程只保留只写 fd ,子进程只保留只读 fd ,这样父进程就可以和子进程进行通信了(父进程写,子进程读)。 -
匿名管道的虚拟文件系统 VFS 对应的底层文件系统实现是基于
pipefs
内存文件系统 -
管道在内存中的实现本质就是一段内核 buffer 内存,不同的文件操作符(一个读一个写)对这段 buffer 进行读写操作。
-
用户态:
read
/write
→ 内核态 VFS:task_struct
→files_struct
→fd_array
→fds[0]
fds[1]
→file0
file1
→file_opts
→inode
→pipe_inode_info
→pipe_bufs
共享内存 (shared memory)
创建共享内存
shmget
- allocates a System V shared memory segment
#include <sys/ipc.h>
#include <sys/shm.h>
// 返回根据 key 生成的 shmid
int shmget(key_t key, size_t size, int shmflg);
参数含义:
-
key
:唯一标识新创建的共享内存 -
size
:共享内存的大小,向上取整成PAGE_SIZE
的倍数 -
shmflg
:一些标志信息IPC_CREAT
:根据key
判断对应的共享内存段是否存在,如果不存在,则创建;如果存在,则返回已经存在的共享内存段IPC_EXCL
: 和IPC_CREAT
一起用,如果已经存在key
对应的共享内存 则失败读写权限信息
映射共享内存
shmat
— 映射共享内存到进程的虚拟地址空间,返回映射的虚拟内存段的起始地址shmdt
— 解除映射,如果成功返回 0,否则返回 -1
#include <sys/types.h>
#include <sys/shm.h>void *shmat(int shmid, const void *shmaddr, int shmflg);
int shmdt(const void *shmaddr);
参数含义:
shmid
:共享内存的唯一标识id
,即填入由shmget
函数返回的值shaddr
: 内存映射起始地址,如果是NULL
的话,内核会分配shaflg
:是一组标志位,通常为0
。
注意:创建和映射共享内存操作只是在内核中维护一些数据结构,并没有真的分配物理内存。真正分配物理内存是在访问这块虚拟内存地址中的数据发生缺页异常时,由缺页异常处理程序维护进程页表中的虚拟页号和物理页号的映射关系的。
这里进程 A 和进程 B 访问的是同一块物理内存上的相同的物理页。
参考代码:
共享内存的底层原理是基于 tmpfs 文件系统:https://www.processon.com/view/link/6277c3921e085327716f5971
总结
-
共享内存的原理:不同进程的虚拟内存地址会映射到相同的物理内存上,这样两个进程通过访问同一块物理内存,达到通信的目的。(一般情况下,不同进程的虚拟地址是映射到不同物理地址的)
-
在创建共享内存时并没有真的分配物理内存,真的分配是进程在读、写数据的时候,发生缺页异常,由缺页异常处理程序分配共享内存(物理内存)的页号到进程的虚拟页表中
-
共享内存的底层原理是基于
tmpfs
文件系统, Linux中一切皆文件
问题:mmap 内存映射和 shm 共享内存有什么区别?
- Linux 中的内存映射是指将一块虚拟地址内存空间和一个文件对象关联起来,以初始化这块虚拟内存的内容,文件对象可以是一个普通磁盘文件,也可以是一个匿名文件(一块只包含二进制零的物理内存)
- mmap 内存映射时,被映射的对象可以是一个磁盘文件,也可以是一个请求二进制零的匿名对象。如果是前者,在发生缺页异常时,缺页异常处理程序除了需要维护页表外,还需要将磁盘文件内容加载到物理内存中;如果是后者,则就相当于将一块物理内存和虚拟内存进行映射。
- shm 共享内存映射是直接每个进程将虚拟内存映射到同一块物理内存,不涉及到磁盘文件。shm 保存在物理内存,这样读写的速度要比磁盘要快,但是存储量不是特别大。
- 所以可以简单的认为 mmap 主要是用于映射磁盘文件的,而 shm 是直接用于映射物理内存的
- mmap 有一个好处是,把文件保存在磁盘上,当设备机器重启时,这个文件还保存了操作系统同步的映像,所以 mmap 不会丢失,但是 shm 就会丢失。
信号量
在一个进程内,多个线程同时更新共享资源,有数据并发安全问题,解决方案有:
- ① 原子操作
- ② 锁机制 - 管程
- ③ 信号量
多个进程同时更新共享内存(共享资源),也有数据安全问题,解决方案:信号量
IPC 的信号量 (semaphore)
原理思想和并发编程中的信号量是一样的,但是两者的实现完全不同:
-
IPC 的信号量实现很复杂,是在内核态中实现的,而并发编程中的信号量是在用户态实现,基于原子操作实现
-
IPC 的信号量是操作系统层面用于解决多个进程之间的共享内存并发读写问题,并发编程中的信号量用于解决同一个进程的多个线程之间的共享资源读写问题
一个是在内核态实现的,一个是应用程序代码中实现的。
参考代码:
消息队列
创建消息队列:msgget
- get a System V message queue identifier
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>int msgget(key_t key, int msgflg); // 函数返回返回新创建的消息队列的 id
参数含义:
-
key
:唯一标识新创建的消息队列 -
msgflg
:一些标志信息IPC_CREAT
:根据key
判断对应的共享内存段是否存在,如果不存在,则创建;如果存在,则返回已经存在的共享内存段IPC_EXCL
:和IPC_CREAT
一起用,如果已经存在key
对应的共享内存,则失败读写权限信息
发送和接收消息:msgsnd
, msgrcv
- System V message queue operations
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); // 返回值:成功返回0;失败返回-1
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtype, int msgflg); // 成功返回接收个数,失败,返回-1
msqid
: 由msgget
函数返回的消息队列的标识符msgp
: 消息缓冲区指针,指针指向准备发送/接收的消息msgflg
: 为0
表示阻塞方式,设置IPC_NOWAIT
表示非阻塞方式异步接发消息msgsz
: 是msgp
指向的消息长度,这个长度不含保存消息类型的那个long int
长整型msgtype
:
等于0
,那么读取消息队列中的第一条消息
大于0
,那么读取消息队列中的第msgtype
条消息(这里是读取类型等于msgtype
的第一条消)
小于0
,那么读取小于等于msgtype
绝对值最小的msgtype
的消息
参考代码:
int main() {int mq_id = get_mq_id(); struct msg_buffer buffer;printf("enter message type: "); scanf("%d", &buffer.mtype);printf("enter message contenit:");scanf("%s", &buffer.mtext);int len = strlen(buffer.mtext) + 1;if (msgsnd(mq_id, &buffer, len, IPC_NOWAIT) == -1) { perror("fail to send message.");exit(1); }return 0;
}
#include <string.h>
#include "mq.h" int main() {int mq_id = get_mq_id(); struct msg_buffer buffer; int type;scanf("%d", &type);if (msgrcv(mq_id, &buffer, 1024, type, IPC_NOWAIT) == -1) { perror("fail to recv message.");exit(1); }printf("received message type : %d, text: %s, \n", buffer.mtype, buffer.mtext); return 0;
}
相关文章:
【操作系统笔记十一】进程间通信
Linux文件系统 inode 节点 (index node):给每个文件赋予一个称为 i 节点的数据结构。 inode 一开始是存储在硬盘中的,只有当文件被打开的时候,其对应的 i 节点才加载到内存中。 总结: Linux 中,…...
【操作系统】聊聊Linux软中断
什么是中断 中断是系统用来响应硬件设备请求的一种机制,会打断进程的正常调度和执行,转而去执行内核中的中断处理程序。 比如你正在看书,你女朋友叫你出去逛街。你就需要先放下手里的事情,然后逛街。回来之后,在接着看…...
公众号迁移个人可以迁移吗?
公众号账号迁移的作用是什么?只能变更主体吗?很多小伙伴想做公众号迁移,但是不知道公众号迁移有什么作用,今天跟大家具体讲解一下。首先公众号迁移最主要的就是修改公众号的主体了,比如我们公众号原来是A公司的&#x…...
全国职业技能大赛云计算--高职组赛题卷⑤(容器云)
全国职业技能大赛云计算--高职组赛题卷⑤(容器云) 第二场次题目:容器云平台部署与运维任务2 基于容器的web应用系统部署任务(15分)任务3 基于容器的持续集成部署任务(15分)任务4 Kubernetes容器…...
支撑位和阻力位在Renko和烛台图如何使用?FPmarkets澳福3秒回答
很多投资者都知道,Renko图表和普通日本烛台都会采用相同的交易信号,即支撑位和阻力位。那么支撑位和阻力位在Renko和烛台图如何使用?FPmarkets澳福3秒回答。 这些信号在任何时间框架上都会出现,且在蜡烛图交易中颇受欢迎。对于Renko图表而言…...
如何在32位MCU用printf()函数打印64位数据
1. 在32位MCU上定义64位变量: unsigned long long time_base; unsigned long long temp_time;2. 调用打印函数: printf("RFID:time_base:%d\r\n",time_base); printf("RFID:temp_time:%d\r\n",temp_time); printf("RFID:Ru…...
Python爬虫程序设置代理常见错误代码及解决方法
Python爬虫程序设置代理是爬虫程序中常用的技巧,可以有效地绕过IP限制,提高爬虫程序的稳定性和效率。然而,在设置代理时,常会出现各种错误代码,这些错误代码可能会影响程序的正常运行,甚至导致程序崩溃。本…...
3D点云目标检测:Centerformer训练waymo数据集
一、环境准备 项目地址:centerformer 1.0、基础环境 python 3.8.0 torch 1.9.1cu111 waymo-open-dataset-tf-2-6-0 1.4.9 spconv 1.2.1 其余按照requirement.txt里安装就行 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt由于我本人是在…...
火山引擎DataLeap推出两款大模型应用: 对话式检索与开发 打破代码语言屏障
更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群 自上世50年代,以“计算机”作为代表性象征的信息革命开始,社会对于先进生产力的认知便开始逐步更迭——从信息化(通常认为是把企…...
windows上配置vscode C/C++代码跳转
windows上配置vscode C/C代码跳转 安装插件 C/C 官方的 C/C 插件,必备的插件,是代码跳转、自动补全、代码大纲显示等功能的基础。 Gtags C/C GNU Global GNU Global除了安装该插件之外,还需要在本地下载安装GNU Global工具。多看下插件…...
【Xilinx】基于MPSoC的OpenAMP实现(一)
【Xilinx】基于MPSoC的OpenAMP实现(一) 一、开发环境1、开发思路2、下载官方bsp包 二、编译Linux1、配置petalinux环境变量2、创建工程3、进入目录4、设置缓存目录(重点:可离线编译,加快编译速度)5、配置u-…...
代码随想录算法训练营总结篇|完结撒花
完结撒花,真不敢相信60天坚持下来了。 算法一直是我的超级超级弱项,属于小白中的小白。一开始是想自己刷的,打开leetcode第一题,吼哟好家伙,梦开始的地方直接破碎。之前刷B站的时候就有学习up推荐算法可以看看代码随想…...
uniapp、vue实现滑动拼图验证码
uniapp、vue实现滑动拼图验证码 实际开发工作中,在登陆的时候需要短信验证码,但容易引起爬虫行为,需要用到反爬虫验证码,今天介绍一下拼图验证码,解决验证码反爬虫中的滑动验证码反爬虫。滑动拼图验证码是在滑块验证码…...
【ArcGIS】土地利用变化分析详解(矢量篇)
土地利用变化分析详解-矢量篇 土地利用类型分类1 统计不同土地利用类型的面积/占比1.1 操作步骤Step1:Step2:计算面积Step3:计算占比 2 统计不同区域各类土地利用类型的面积2.1 操作步骤 3 土地利用变化转移矩阵3.1 研究思路3.2 操作步骤 4 分…...
VS2022创建控制台应用程序后没有Main了,如何显示Main?
文章目录 问题描述原因解决方案简单的顶级语句试用计算器 其他文章 问题描述 用VS2022创建一个控制台应用后,没有名称空间和Main函数了,只有一个WriteLine,如下所示。 // See https://aka.ms/new-console-template for more information Co…...
当当网商品详情数据接口
当当网商品详情数据接口可以通过当当网的开放平台获取相关信息。您可以注册当当开放平台账号,并按照要求提交申请获取API接口的调用凭证。获得授权后,您将会收到一组AccessKey和SecretKey。使用编程语言(如Java)调用API接口&#…...
ultraEdit正则匹配多行(xml用)
在ultraEdit中,我想选取<channel到</channel>之间的多行(进行删除)。在perl模式下,命令为“<channel[\s\S]?</channel>”。下面是xml文件: <!--This XML file does not appear to have any sty…...
Mac上的utools无法找到本地搜索插件
utools安装地址 utools本地搜索用法 目前本地搜索只在win下,mac无福了 Mac可用cmdspace方法使用聚焦搜索,来搜索本地文件...
docker部署nginx下日志自动切割方法
前言:nginx采用docker部署,简单方便,但出现一个问题,就是日志没有自动切割,导致access.log 无限增大。如果非docker安装,则nginx的日志默认有切割的,那docker为何没有呢,最后发现&am…...
3D目标检测实战 | 图解KITTI数据集与数据格式
目录 1 数据集简介2 传感器坐标系3 数据集下载与组织4 数据内容说明4.1 矫正文件calib4.2 图像文件image4.3 点云文件velodyne4.4 标签文件label4.5 平面文件plane 1 数据集简介 KITTI数据集是一个广泛应用于自动驾驶和计算机视觉领域的公开数据集。该数据集由德国卡尔斯鲁厄理…...
周界警戒AI算法+视频智能分析在安全生产场景中的应用
长期以来,周界防范安防系统在大型园区、工厂、社区、机场、火车站站台、重点单位等领域应用较为广泛和常见。随着AI人工智能等新兴技术的快速发展与落地应用,通过AI智能检测与视频智能分析技术,现代化的周界安防系统可以做到全天候快速、准确…...
C++中执行shell命令,popen与system的区别
C中执行shell命令,popen与system的区别_c popen_Op_chaos的博客-CSDN博客 2.system system()函数执行过程: 1.fork一个子进程; 2.在子进程中调用exec函数去执行command; 3.在父进程中调用wait去等待子进程结束。 由于system没…...
Flink相关
墨滴社区 用 Flink 取代 Spark Streaming!知乎实时数仓架构演进_天池技术圈-阿里云天池 关于flink实时数仓的实际问题_flink datastream 按天,小时写入hdfs_一个写湿的程序猿的博客-CSDN博客 基于 Flink Hudi 的实时数仓在 Shopee 的实践 - 墨天轮...
数据结构题型9-顺序栈
#include <iostream> //引入头文件 using namespace std;typedef int Elemtype;#define Maxsize 10 #define ERROR 0 #define OK 1typedef struct {Elemtype data[Maxsize];int top; }SqStack;void InitStack(SqStack& S) {S.top -1; } bool StackEmpty(SqStack…...
时间复杂度、空间复杂度
一、时间复杂度 1、概念 时间复杂度:计算的是当一个问题量级增加的时间,时间增长的趋势; O(大O表示法):渐进的时间复杂度 2、举例 ① 以下 for 循环的时间复杂度:O(1 3n) O(n) 去掉常数…...
C++---多态
多态 前言多态的概念多态的定义及实现多态的构成条件虚函数虚函数的重写虚函数重写的两个例外协变(基类与派生类虚函数返回值类型不同)析构函数的重写 override和final 虚函数的默认参数 抽象基类 前言 在买火车票的时候,如果你是学生,是买半价票&#…...
Android 滑动事件消费监控,Debug 环境下通用思路
Android Debug 环境下滑动事件消费监控通用思路 背景 Android 开发中,经常会遇到滑动事件冲突。在一些简单的场景下,我们如果能够知道是那个 View 拦截了事件,那我们能够很容易得解决。解决方法通常就是内部拦截法或者外部拦截法。ViewPage…...
Unity中Shader用到的向量的乘积
文章目录 前言一、向量的乘法1、点积2、差积 二、点积(结果是一个标量)1、数学表示法2、几何表示法 三、叉积1、向量叉积的结果 与 两个相乘的向量互相垂直2、判断结果正负方向的方法:右手法则 前言 Unity中Shader用到的向量的点积 一、向量…...
帆软FineReport决策报表之页面布局
最近在用帆软决策报表绘制首页大屏,记录使用过程,方便查看。 版本:FineReport10.0 第一步、页面布局 页面布局其实就是组件的排列组合,决策报表主区域body有两种布局方式:自适应布局和绝对布局。 1)自适应…...
门户网站开发维护合同/seo关键词排名优化推荐
mysql的锁概念:当一个会话操作一个表的时候,另一个会话也可以操作这个表,那么最终导致结果看谁操作的块一点谁生效,这个时候就需要锁的机制。当一个会话操作的时候,锁住这个表,直至操作完成。锁的分类&…...
南阳网站排名优化价格/百度平台商家联系方式
一、概述 之前小编我写了一遍内置函数第一篇,因为内置函数的内容太多了,所以小编把它分开写了,防止太多搞乱了。 内置函数博客地址:猛击这里 二、内置函数详情 1、filter(function, iterable) 功能:通过function过滤条…...
wordpress安装后后台无css/南宁网站关键词推广
在开始之前先了解下js数据类型 js基本数据类型: null undefined number boolean string js引用数据类型: function object array 一说instanceof 就想到typeof ,这里也介绍下typeof: typeof是用来判断数据类型的,就一个参数 ,使用…...
电子商务网站开发技术和工具有哪些/独立站seo是什么意思
有客户反映,某个功能的前3页数据是一样的,后来检查发现确实如此。看看sql的查询结果,确实是前三页一样的,感觉sql也没什么问题,上网查询资料发现,是因为排序字段的问题。 SELECT* FROM(SELECTbb.*, ROWNUM …...
万户做网站好不好/网站设计的流程
kotlin jsonWelcome to a brand new tutorial for Easy Android Programming. In the tutorial, we are going to learn about the basic usage of retrofit in kotlin for fetching JSON from a remote server.欢迎使用全新的Easy Android编程教程。 在本教程中,我…...
政府网站集约化建设试点/seo是什么服务器
写在前面 业务逻辑是这样的,需要导出一个app的话题,并需要把该话题下帖子的附件导出,然后需求想修改成人员的名称.jpg的格式。所以就出现了中文乱码的问题。在本地没问题,但发布到服务器上面就出问题,每次打包下载下面…...