简明linux系统编程--共享内存消息队列信号量

news2024/9/20 2:55:12

目录

1.父子进程共享内存

1.1基本说明

1.2主要步骤

 1.3shmget函数介绍​编辑

1.4函数返回值

1.5shmat函数介绍

1.6shmdt函数介绍

1.7结合代码理解

2.非亲缘关系的进程的共享内存通信

2.1和上面的区别

2.2如何通信

2.3具体代码

3.父子进程消息队列

4.非亲缘关系的进程的消息队列 

5.信号量的介绍

5.1基本说明

5.2进程控制

5.3函数介绍

5.4代码说明

6.命名信号量(无亲缘关系)

7.信号量线程同步


1.父子进程共享内存

1.1基本说明

共享进程就是多个进程都可以使用的,但是为了不影响进程的连续性,我们的系统会把这个共享的内存映射到每一个独立的进程空间里面去;

按照下面的这个图进行理解,我们的这个共享内存会映射到这个AB里面各一份,AB是两个各自独立的进程,这个时候,AB对于映射到自己进程的这个小的空间进行操作就是相当于对于这个大的共享内存进行操作;

1.2主要步骤

其实整个列成只需要4个步骤:

  • 建立共享内存,
  • 把共享内存映射到AB进程里面去,
  • 解除映射和绑定的关系,
  • 删除共享内存,

但是第四个需要根据实际情况决定是否要删除,如果多个进程都要使用,删除这个共享内存之后,可能某些进程就会受到影响;

 1.3shmget函数介绍

key(键值)指的就是共享内存的一个编号,是在内核层面进行标识的;

但是在应用层上面,我们使用的是标识符(IPC_CREATE)进行标记的;

size就是这个共享内存的大小;

其中这个函数参数的第三个IPC_CREAT就是指的当我们创建共享内存单元的时候,如果这个共享内存单元不存在,我们就创建,已经存在的话,我们就尝试去访问打开这个共享内存;

1.4函数返回值

返回的就是应用层的共享内存的描述符,就是上面说到的这个identifier;

1.5shmat函数介绍

shmat把共享内存的标识符映射到调用的进程的地址空间里面,实际上就是一个映射的过程;

第一个参数就是标识符,我们把这个共享内存映射到进程的哪一个地方,我们可以指定,需要给出来具体地址,但是也可以使用null让这个操作系统给我们分配位置

第三个参数,就是这个shmflg,如果我们写成0,就是进程对于这个映射过来的共享内存具有读写权限,当然,我们可以设置为只读或者是只写的权限,但是我们写成0就可以了;

返回值,表示的映射的地址空间的首地址,就是这个进程里面映射区域的首地址

1.6shmdt函数介绍

shmat函数就是用来进行这个解除共享内存在这个进程里面的映射,从而让这个共享内存在这个映射区域里面不会发挥作用;

1.7结合代码理解

  •  首先我们就是shget函数创建共享内存,IPC_CREATE就是应用层上面的标识符,用来区分共享内存的,类似于每一个人的身份证号码;
  • fork函数就是创建这个父子进程,其中这个子进程返回值是0,父进程返回值是这个子进程的pid,因此这个父进程的返回值大于0;
  • 首先进入的就是父进程的分支语句,我们的这个父进程把这个映射的区域进行清除之后,把这个msg这个信息写代映射的这个空间里面去,相当于间接对于共享内存进行操作,然后解除这个共享内存的区域
  • 我们的这个子进程需要sleep一段时间,读取这个共享内存里面的内容,最后打印输出;
  • 同时这个里面使用了wait_pid函数,让这个父进程进行等待,等待这个子进程完成任务,就是一个进程等待;

2.非亲缘关系的进程的共享内存通信

2.1和上面的区别

上面的这个是父子进程,两个是有亲缘关系的,但是这个时候我们的两个进程是完全独立运行的,两个之间没有任何的关系;

2.2如何通信

就是我们上面的这个进行共享内存创建的时候,使用的是这个shmget函数的IPC_PRIVATE参数,就这个参数而言,父进程和子进程是相同的,因为这个子进程完全拷贝我们的父进程的代码和数据

但是如果是两个不相关的进程,我们肯定是一个进程进行read操作,一个进程进行write操作,这个read进程把这个写的内容进行读取,这个时候我们的两个进程里面肯定是要各自去创建共享内存的,而且这个shmget函数的第一个参数需要是一样的,否则我们的一个进程写进去之后,另外一个进程根本无法进行读取;

上面的是因为父子进程的这个第一个参数是一样的,所以这个可以使用默认值,他们也可以找到写入的数据,但是这个没有亲缘关系的两个进程,如果不进行这个参数的指定,读的进程是根本找不到这个内从写到哪里呢,就也不知道去哪里读,这个就是和上面的父子进程最大的区别;

2.3具体代码

负责写内容的进程,可以看到这个里面是设置了一个宏常量进行这个参数的制定的,而且两个进程的这个参数值是一样的,这样这个数据才可以被正常的读取;

负责读取内容的进程:

3.父子进程消息队列

描述符标识符就是这个函数的返回值,返回值和我们的这个key相互关联,这个key是在我们的内核层,就是键值,应用层使用的就是identifier进行区分;

下面的这个msgget函数就是创建一个消息队列,我们的父进程使用一个函数megsnd发送消息的内容到这个队列里面去,我们的子进程通过一个函数msgrcv读取这个父进程放到这个消息队列里面的内容;

  • 我们的这个结构体里面的内容就是这个消息队列的内容的组成,其中这个父进程写入数据到这个消息队列里面,这个子进程获取数据;
  • 因为这个结构体里面包含了这个数据类型的大小,因此我们计算这个发送内容的大小的时候,使用的是这个结构体的大小减去这个里面的这个类型的大小;
  • 我们的这个消息队列和共享内存的最大差别就是:消息队列里面的一个结构体可以一次性传递不同类型的数据,这个是有这个结构体组成内容控制的;
  • 这个里面的buf这个结构体,子进程和父进程都是有的,因为这个子进程拷贝了这个父进程的数据和代码;

4.非亲缘关系的进程的消息队列 

非亲缘关系的进程之间的这个消息的传输也是可以进行的,只要我们的这个接收端前往和发送端的消息号相同的消息队列里面去读取内容就是可以成功的;

也就是这个msgrcv函数里面的倒数第二个参数需要我们的发送端的这个消息数据的类型号是一样的,这样才可以保证消息的准确传输;

发送端的进程:

接收端的进程:

5.信号量的介绍

5.1基本说明

管道,共享内存和消息队列都是进行这个数据的传输的,一个资源想要被多个进程访问,就是进行同步,信号量就是进行任务之间的同步;

信号量就是一个整数值,A访问资源的时候,检查信号量是不是大于0,B进程也想要访问这个内存,B进程也是需要检查这个进程的信号量是不是大于0的,这个时候进程B处于阻塞状态,直到这个信号量大于0,才会继续运行;

信号量进行工作的时候,如果被设置为1,一个进程访问之后,就会被消耗为0,这个时候其他的进程想要访问这个内存的时候,其他的想要访问的进程就会处于阻塞的状态

5.2进程控制

我们的这个信号量也是划分为无名的信号量和有名的信号量,这个和我们当时学习的管道是一样的逻辑,因为我们的管道也是划分为这个有名管道和无名管道的;

对于这个进程的控制,因为这个信号量是可以进行消耗和发布的,例如这个信号量只是1,我们的父进程使用这个资源,消耗掉了这个信号量,这个时候的父进程就会处于阻塞的状态,因为只有这个信号量大于0 的时候这个才是可以正常运行的,这个时候,我们的子进程负责发布信号量,这个时候我们的子进程什么时候发布这个信号量,我们的父进程就会从这个阻塞状态变为正常的运行状态;

因此这个子进程发布信号量的时刻决定了这个父进程从阻塞状态转换为正常运行状态的时刻,因此这个就间接的实现了我们的子进程对于父进程的控制;

5.3函数介绍

sem_init函数的用法就是创建信号量,用来被其他的进程使用;

sem_wait函数的用法就是检查这个信号量是不是大于0,如果大于0,我们的进程就可以使用,如果不是我们就需要被处于阻塞状态;

sem_post函数作用就是进程发布信号量,让处于阻塞的进程正常运行;

mmap函数就是产生虚拟的地址空间,让这个父进程和子进程共享这个生成的地址空间,从而让这个子进程增加的信号量可以被子进程看到,否则我们的子进程发布的信号量无法被父进程看到;

5.4代码说明

这个代码就是综合上面的函数以及这个父子进程的这个行为,实现的子进程增加信号量,当我们的父进程因为消耗掉信号量处于阻塞状态的时候,能够看到这个子进程的发布而让这个阻塞的进程运行起来;

6.命名信号量(无亲缘关系)

创建一个父进程,消耗信号量,创建一个子进程,发布信号量控制第一个进程的状态:

7.信号量线程同步

这个主要介绍一下区别,就是我们的进程之间是相互独立的,因此我们需要使用这个mmap函数创建一个寻你的空间让两个进程之间的信号量可以相互看到,但是对于进程而言,多个线程公用一个进程的资源,因此这个是可以直接进行这个信号量的传递的,不需要使用这个mmap函数进行信号量的虚拟地址的开辟,两个线程使用的这个信号量本来就是属于相同的进程的,因此他们是可以相互看到的,不需要使用这个mmap函数;

下面的这个代码就是调用这个pthread函数进行现成的创建,使用这个sem_wait函数消耗信号量,使用sem_post去发布信号量;

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

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

相关文章

极狐GitLab 重要安全版本:17.3.3, 17.2.7, 17.1.8, 17.0.8, 16.11.10

GitLab 是一个全球知名的一体化 DevOps 平台,很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版,专门为中国程序员服务。可以一键式部署极狐GitLab。 学习极狐GitLab 的相关资料: 极狐GitLab 官网极狐…

BitLocker硬盘加密的详细教程分享

硬盘加密是将数据转换为一种只有授权用户才能读取的形式。通过使用加密算法,硬盘上的数据在存储时被加密,只有输入正确的密钥或密码才能解密和访问这些数据。 硬盘加密的重要性 数据是现代社会的重要资产,保护这些数据免受非法访问和窃取至关…

Mobile net V系列详解 理论+实战(2)

Mobilenet 系列 实践部分一、数据集介绍二、模型整体框架三、模型代码详解四、总结 实践部分 本章针对实践通过使用pytorch一个实例对这部分内容进行吸收分析。本章节采用的源代码在这里感兴趣的读者可以自行下载操作。 一、数据集介绍 可以看到数据集本身被存放在了三个文件…

处理RabbitMQ连接和认证问题

在使用RabbitMQ进行消息队列管理时,我们可能会遇到各种连接和认证问题。本文将介绍如何诊断和解决这些问题,并通过使用RabbitMQ的管理端进行登录验证来确保配置正确。 1. 问题概述 在最近的一次部署中,我们遇到了两个主要问题: …

一对一,表的设计

表很大,比如用户 用户登录只需要部分数据,所以把用户表拆成两个表 用户登录表 用户信息表 一对一设计有两种方案: 加外键,唯一 主键共享

学生考试成绩老师发布平台

老师们一直肩负着传授知识与评估学生学习成果的双重责任。其中,发布学生考试成绩是教学过程中不可或缺的一环。然而,传统的成绩发布方式往往繁琐且耗时。老师们需要手动整理成绩,然后通过电话、短信或电子邮件逐一通知学生和家长,…

Jenkins设置自动拉取代码后怎么设置自动执行构建任务?

在 Jenkins 中设置自动拉取代码后,可以通过以下步骤设置自动执行构建任务: 一、配置构建触发器 打开已经设置好自动拉取代码的 Jenkins 任务。在 “构建触发器” 部分,除了 “Poll SCM”(用于定时检查代码仓库更新)外…

Mybatis 和 数据库连接

第一次要下载驱动 查询数据库版本 但是在idea查看数据库我不行,插件我也装了,然后我在尝试改版本。也不行。 爆错 感觉还是插件的问题。先不弄了,影响不大。 但是加载了这个,能在idea写sql语句,还能有提示。

【IPOL阅读】点云双边滤波

文章目录 简介点云滤波处理结果 简介 IPOL,即Image Processing On Line,理论上是一个期刊,但影响因子很低,只是个SCIE,按理说没什么参考价值。但是,这个网站的所有文章,都附带了源代码和演示窗…

【三步搭建 本地 编程助手 codegeex】

这里写目录标题 第一步 ollama安装常见报错 第二步 下载启动模型下载启动模型常见问题 第三步配置codegeex安装插件本地配置 其他 如果可以联网,vscode装个codegeex插件即可,本次搭建的本地编程助手,解决因安全问题完全无网络的情况下的编程助…

诗文发布模板(python代码打造键盘录入诗文自动排版,MarkDown源码文本)

python最好用的f-string,少量代码打造键盘录入诗文自动排版。 (笔记模板由python脚本于2024年09月19日 19:11:50创建,本篇笔记适合喜欢写诗的pythoner的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网:https://www.python.org/ Free&am…

新手入门大模型教程(非常详细)零基础入门到精通,收藏这一篇就够了

目前大模型非常的火,国内开始流行大模型应用,那么作为程序员对于大模型有什么要了解和学习的我们今天就来研究下。 深度学习基础 因为大模型也是人工智能,人工智能就要先学习一下深度学习,深度学习是机器学习领域中的一个方向。…

Linux通过yum安装Docker

目录 一、安装环境 1.1. 旧的docker包卸载 1.2. 安装常规环境包 1.3. 设置存储库 二、安装Docker社区版 三、解决拉取镜像失败 3.1. 创建文件目录/etc/docker 3.2. 写入镜像配置 https://docs.docker.com/engine/install/centos/ 检测操作系统版本,我操作的…

英飞凌最新AURIX™TC4x芯片介绍

概述: 英飞凌推出最新的AURIX™TC4x系列,突破了电动汽车、ADAS、汽车e/e架构和边缘应用人工智能(AI)的界限。这一代面向未来的微控制器将有助于克服安全可靠的处理性能和效率方面的限制。客户将可缩短快速上市时间并降低整体系统成本。为何它被称为汽车市场新出现的主要颠覆…

SourceTree保姆级教程1:(克隆,提交,推送)

本人认为sourceTree 是最好用的版本管理工具,下面将讲解下sourceTree 客户端工具 克隆,提交,推送 具体使用过程,废话不多说直接上图。 使用步骤: 首先必须要先安装Git和sourceTree,如何按照参考其它文章&…

计算机网络:概述 --- 体系结构

目录 一. 体系结构总览 1.1 OSI七层协议体系结构 1.2 TCP/IP四层(或五层)模型结构 二. 数据传输过程 2.1 同网段传输 2.2 跨网段传输 三. 体系结构相关概念 3.1 实体 3.2 协议 3.3 服务 这里我们专门来讲一下计算机网络中的体系结构。其实我们之前…

力扣1143-最长公共子序列(Java详细题解)

题目链接:1143. 最长公共子序列 - 力扣(LeetCode) 前情提要: 如果你做过718. 最长重复子数组 - 力扣(LeetCode)并且看过我的这篇题解力扣718-最长重复子数组(Java详细题解)-CSDN博…

大数据新视界 --大数据大厂之SaaS模式下的大数据应用:创新与变革

💖💖💖亲爱的朋友们,热烈欢迎你们来到 青云交的博客!能与你们在此邂逅,我满心欢喜,深感无比荣幸。在这个瞬息万变的时代,我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

网站在线客服插件配置

使用工具:百度爱番番 下载地址: 百度爱番番—企业的一站式智能营销管家 一、下载百度爱番番APP,注册账号 二、 登录app 三、点击设置——站点设置——新建站点 四、设置站点名称——站点地址——PC站点——确定 五、点击配置好的站点的获取代…

Linux新增用户,对用户提权

文章目录 一、创建用户二、删除用户三、对用户进行提权 一、创建用户 adduser进行创建用户,名字最好不用和指令名称相同。 在创建完用户时最好使用sudo passwd username进行对用户密码的修改. 二、删除用户 userdel进行对用户的删除 三、对用户进行提权 新建用…