进程间通信(System V 标准下的多种通信方式)

上一篇文章讲了进程间通信的一个方式之一:管道,也提到管道存在的字节流问题。这篇文章将讲到基于System V 标准的多种通信方式,包括:共享内存,信号量,消息队列。

共享内存

共享内存是最快的 IPC 形式 ,它的本质是在内存空间中的共享区开辟一块空间供用户直接使用,这样在对数据写入与读取时可以绕开内核的系统调用,达到极致的速度。(但是当多个进程同时读取同一块空间时会出现竞态条件,此时要搭配信号量、互斥锁等做同步,这部分还是需要内核支持的)。

来认识一下共享内存相关的几个函数:

用于创建共享内存的:

用于将共享内存段连接道进程地址空间的:

用于将共享内存段与当前进程脱离的:

用于控制共享内存的:

对于每个函数的参数含义就不做说明了,可以使用 man 命令自行查看。

共享内存不会有管道那样的读取数据问题,因为共享内存是大小固定的区域,你往这个区域里面写什么,读取时读到的就是什么。

共享内存不会自带同步机制,就是前面说的多个进程同时访问时,这个时候我们需要将共享内存保护起来,不然会出现数据错乱。保护方法有信号量、互斥锁,互斥锁我们没有学过,但信号量是接下来的话题,不妨先学习了信号量再考虑它是如何实现保护共享内存的功能的。

信号量

信号量本质是一个计数器,这里又涉及到了引用计数的概念,用来表示临界资源中资源的数量多少。在进程要访问资源之前,需要先申请信号量,也就是对一块资源的 "预定"。

我们把共享内存空间想象成一个电影院,申请信号量的行为就是买票。你坐在电影院的哪一个座位,你的票是决定因素,如果没有票,就可能出现座位使用权的争执。

那么,信号量如何解决共享内存的问题呢?首先我们得知道,信号量本身就是一个共享的资源,可以理解为每个人都可以看到电影院的座位预定情况。对于一块共享内存,如果已经有进程在访问,那么其他进程便不能访问,当那个进程访问完共享内存并主动释放信号量,下一个进程才能访问。

申请信号量,P操作,释放信号量,V操作。

消息队列

消息队列就是将要共享的资源维护成一个队列。

消息队列的形式:A写入一个信息,内核存起来,B随时来取用,写端完全不影响读端。有点像弄了很多个大小不一的共享内存,然后串联起来。

它每一块数据都有边界,所以不会出现管道那样的问题。它自带同步机制,不会因为多个进程同时访问导致数据错乱。

System V

以上三种通信方式都是 System V 标准下的,那么什么是System V标准呢?为什么要用System V标准呢?

首先,System V标准其实就是一种 进程间通信的思路,它的特点是:内核对象全局可见,像上面的共享内存,信号量和消息队列,其实它们的创建都需要一个 Key,只要知道同一个 Key ,任何进程都能打开这些共享的资源。

正是这种特性,让 System V 下的 IPC 都可以被当作同一种资源来管理。

在内核中有一个 ipc_id_ary 结构体,里面有一个柔性数组( p0 ),用来存放这些资源,它们本质相同,所以可以存放在同一个数组中,所有 IPC 对象都共享一个通用头部struct kern_ipc_perm),包含 key、id、权限等信息。

内核通过 ipc_id_ary 统一管理,而具体的类型(共享内存 / 信号量 / 消息队列)通过后续的强转来区分,不属于该类型的强转则得不到正确的信息,这就是使用System V标准的意义,也是用C语言实现出多态的高级教科书!

相关推荐
Emily156853598701 小时前
ABB CI867K01 3BSE043660R1
服务器·plc·dcs·abb·ci867k01·3bse043660r1·工控模块
考虑考虑1 小时前
docker compose环境变量替换
运维·后端·自动化运维
Java陈序员2 小时前
轻量运维面板!一款现代化的服务器控制面板工具!
运维·服务器·python·react.js·github
bosins2 小时前
WSL 迁移指南:如何将 Linux 环境完整复制到另一台电脑
linux·运维·服务器
IT利刃出鞘2 小时前
Docker Compose--安装WordPress--方法/示例
运维·docker·容器
企鹅的蚂蚁3 小时前
LubanCat RK3588 实时 Linux 开发(六):启用 gs_usb 驱动并完成 USB-CAN 收发
linux·rk3588·linux驱动·socketcan·gs_usb·usb-can
2601_962299884 小时前
Linux执行Python脚本方法
linux·python·脚本·解释器·shebang
snow@li4 小时前
服务器运维:Linux命令速查手册(全景梳理)
linux·服务器·网络
handler014 小时前
【Linux】线程与虚拟内存的底层世界
linux·运维·服务器·c++·线程·虚拟地址空间·共享内存
布莱克6054 小时前
TCP 三次握手与四次挥手详解
服务器·网络·tcp/ip·计算机网络·网络编程