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

Linux:进程间通信---消息队列信号量

文章目录

      • 1.消息队列
        • 1.1 消息队列的原理
        • 1.2 消息队列的系统接口
      • 2. 信号量
        • 2.1 信号量的系统调用接口
      • 3. 浅谈进程间通信
        • 3.1 IPC在内核中数据结构设计
        • 3.2 共享内存的缺点
        • 3.3 理解信号量

  • 序:在上一章中,我们引出了命名管道和共享内存的概念,了解了他们的底层原理和系统接口的使用,知道了共享内存的特性等,而本章,我将继续深入System V的剩下两种进程间通信的方式:消息队列和信号量!!!

1.消息队列

System V IPC{
System V —消息队列
System V —共享内存
System V —信号量
}
本章将围绕着system V IPC中的消息队列和信号量来讲述

1.1 消息队列的原理

消息队列的原理图:
在这里插入图片描述
消息队列的
1. 必须让不同进程看到同一个队列
2. 允许不同的进程,向内核中发送带类型的数据块

文件缓冲区----管道
内存块----共享内存
队列----消息队列
这些都符合进程间通信的本质:必须让不同进程看到同一份资源!!!

1.2 消息队列的系统接口

要想使用消息队列实现进程间通信,首先就要先将消息队列创建出来。
在这里插入图片描述
第一个参数是通过ftok()函数生成的key,第二个参数是位图参数,和之前的共享内存一样,这个函数可以创建一个新的消息队列

想要修改消息队列的属性,就要调用相关的系统接口。
在这里插入图片描述

向消息队列中发送和得到数据:
在这里插入图片描述
其中,msgsnd是发送数据的系统调用接口,msgrcv是获取数据的系统调用接口

消息队列的管理结构体:
在这里插入图片描述

查看消息队列

ipcs -q 能查看消息队列信息(和ipcs -m查看共享内存一样)

删除消息队列

ipcrm -q +[msgid] 能删除消息队列

2. 信号量

2.1 信号量的系统调用接口

要想使用信号量,和消息队列,共享内存同理,也是要先去申请一个信号量。
在这里插入图片描述

和消息队列,共享内存同理,想要修改信号量的属性,就要调用相关的系统接口。
在这里插入图片描述

信号量的管理结构体:
在这里插入图片描述

3. 浅谈进程间通信

3.1 IPC在内核中数据结构设计

在操作系统中,所有IPC资源,都是整合进操作系统的IPC模块中的!
在这里插入图片描述

共享内存、消息队列和信号量这三个的管理结构体内都有一个ipc_perm的结构体,系统通过一个数组对这样的一个个结构体进行管理,从而对不同的IPC结构体进行管理!!!

通过在struct ipc_perm数组中存入对应IPC结构体中ipc_perm结构体的地址,我们就可以通过这个对这个ipc_perm进行处理为((struct semid_ds * )addr)(以信号量的IPC结构体为例),从而访问到整个IPC结构体中的任意成员!!!(其中,ipc_perm中有一个类型标志位,所以操作系统能区分指针指向的对象的类型,也就知道了这是共享内存的IPC结构体还是消息队列的IPC结构体,还是信号量的IPC结构体)

这种模式与c++中的多态有很大的相似度,对于ipc_perm结构体的复用,就像ipc_perm是基类,其他IPC结构体是子类,而实际上cpp就是基于Linux中的这些模式,而引入的多态的概念!!!

3.2 共享内存的缺点

在这里插入图片描述
当我们的A正在写入,且已经写入了一部分,就被B拿走了,导致双方发送和收到的数据不完整-----数据不一致问题,共享内存会有这样的问题,而管道则没有,因为,管道会有同步互斥的保护机制。

1. A、B看到同一份资源,共享内存,如果不加保护,就会导致数据不一致问题
2. 加锁—互斥访问—任何时刻,都只允许一个执行流访问共享资源—互斥(例如:去ATM机取钱的时候,一台ATM机一次只能有一个人取钱或存钱)
3. 共享的,任何时刻只允许一个执行流访问的资源—临界资源—(管道)一般是内存空间。
4. 访问临界资源的代码—临界区

问题一:多进程,多线程,并发打印,此时显示器上的消息是错乱的,甚至和命令行混在一起,这是为什么?

在多进程、多线程中,显示器是一种共享资源,此时,多进程、多线程往显示器打印内容就会导致数据不一致问题,要想不错乱,就要将这个共享资源变成一种临界资源。

3.3 理解信号量

信号量的本质是一把计数器,类似但不等于一个int cnt = n;是用来描述临界资源中资源数量的多少
例子:当我们看电影时,我们还没去看,但是要先买票(买票的本质就是对资源的预定机制),其中票数计数器,每卖一张票,计数器就要减一。此时放映厅的资源就少一个!!!当票数计数器到0后,资源已经被申请完了。

问题一:我们最怕什么情况?

1. 多个执行流访问同一个资源
2. n个执行流访问n-1个资源

为了解决这种问题,我们就要引入一个计数器!!!
int cnt = 15;
int number = cnt–;申请资源
cnt <= 0;资源就被申请完了,再有执行流申请也不会给了!!!

1. 申请计数器资源成功,就表示我具有了访问资源的权限了。
2. 申请了计数器资源,我当前访问我要的资源了吗?没有!申请了计数器资源是对资源的预定机制。
3. 计数器可以有效保证进入共享资源的执行流的数量
4. 每一个执行流,想访问共享资源的时候,不是直接访问,而是先申请计数器资源,就像是看电影先买电影票

程序员把这样一个计数器叫做信号量!!!

所以,当该票只有一个人能抢到,只有一个人能去看电影时。看电影期间只有一个执行流在访问临界资源—互斥!!!

我们把值只能为1,0两态的计数器叫做二元信号量—本质就是一个锁。
当计数器为1.本质问题:其实就是将临界资源不要分成很多块了,而是当做一个整体,整体申请,整体释放!!!

问题二:要访问临界资源,先要申请信号量计数器资源,但是信号量计数器的本质不也是共享资源吗???所以这个计数器也是不安全的

信号量:
a. 申请信号量,本质是对计数器减减------p操作
b. 释放资源,释放信号量,本质是对计数器进行加加操作------v操作

其中信号量的申请和释放—pv操作–是原子的(一个事,要么不做,要做就做完!)
其中要强调的是,多个信号量和信号量是不同的概念

问题二:信号量凭什么是进程间通信的一种?他也没传送数据啊,不是说他的本质就是个计数器吗?

1. 通信不仅仅是通信数据,互相协同也是
2. 要协同,本质也是通信,信号量首先要被所有的通信进程看到。

总结:

本章节带领大家从原理和系统接口的视角了解了什么是消息队列和信号量,而后对进程间通信的内核数据结构进行了探讨,了解了其中的底层逻辑,最后再次深入了解什么是信号量,希望对大家能有帮助!!!

相关文章:

  • Linux 信号终篇(总结)
  • HTTP/3展望、我应该迁移到HTTP/2吗
  • LeetCode 270:在二叉搜索树中寻找最接近的值(Swift 实战解析)
  • 从父类到子类:C++ 继承的奇妙旅程(2)
  • LinkedList源码解析
  • 嵌入式硬件篇---麦克纳姆轮(简单运动实现)
  • 【金仓数据库征文】国产数据库KingbaseES安装与使用详解
  • 深度解析 MySQL 与 Spring Boot 长耗时进程:从故障现象到根治方案(含 Tomcat 重启必要性分析)
  • Java与Go语言对比教程
  • LeetCode --- 448 周赛
  • MCP项目实例 - client sever交互
  • AZScreenRecorder最新版:功能强大、操作简便的手机录屏软件
  • LangGraph(三)——添加记忆
  • 《算法导论(第4版)》阅读笔记:p17-p27
  • 事务连接池
  • Linux笔记---System V共享内存
  • 海市蜃楼的形成原理
  • JVM之内存管理(二)
  • vue 组件函数式调用实战:以身份验证弹窗为例
  • 数字相机的快门结构
  • 国内大模型人才大战打响!大厂各出奇招
  • 观察|天空之外的战场:官方叙事、新闻与社交平台中的印巴冲突
  • 宇数科技王兴兴:第一桶金来自上海,欢迎上海的年轻人加入
  • 深圳市政协原副主席王幼鹏被“双开”
  • 七大交响乐团在沪“神仙斗法”,时代交响奏出何等时代新声
  • 俄罗斯今日将举行“胜利日”阅兵,有何看点?