【Linux学习】进程间通信 (3) —— System V (1)

下面是有关进程通信中 System V 的相关介绍,希望对你有所帮助!

小海编程心语录-CSDN博客

目录

1. System V IPC

1. 消息队列 msg

消息队列的使用方法

1.1 消息队列的创建

1.2 向消息队列发送消息

1.3 从消息队列接收消息

1.4 使用msgctl函数显式地删除MSG对象

2.共享内存 shm

使用共享内存的一般步骤

2.1 创建或打开SHM

2.2 获取共享内存地址

2.3 解除映射

2.4 共享内存控制函数

3. 信号量 sem

3.1 基本概念

3.2 P/V操作

3.3 核心API及实现步骤


1. System V IPC

System V IPC包括消息队列、共享内存、信号量,V 是罗马数字 5,是 Unix 的AT&T 分支的其中一个版本,一般习惯称呼他们为IPC对象,这些对象的操作接口都比较类似,在系统中他们都使用一种叫做 key 的键值来唯一标识,而且他们都是“持续性”资源--即他们被创建之后,不会因为进程的退出而消失,而会持续地存在,除非调用特殊的函数或者命令删除他们。

 它们有如下共同的特性:

在系统中使用所谓键值(KEY)来唯一确定,类似于文件系统中的文件路径

当某个进程创建(或打开)一个IPC对象时,将会获得一个整型ID,类似于文件描述符

IPC对象属于系统,而不是进程,因此在没有明确删除操作的情况下,IPC对象不会因为进程的退出而消失

- 查看IPC对象
ipcs -q/m/s/a- 删除IPC对象
ipcrm -Q key : 删除指定的消息队列
ipcrm -q id : 删除指定的消息队列ipcrm -M key : 删除指定的共享内存
ipcrm -m id: 删除指定的共享内存ipcrm -S key : 删除指定的信号量
ipcrm -s id: 删除指定的信号量

1. 消息队列 msg

消息队列可以认为是一个消息列表。消息队列提供一种带有数据标识的特殊管道,使得每一段被写入的数据都变成带标识的消息,读取该段消息的进程只要指定这个标识就可以正确地读取,而不会受到其他消息的干扰,从运行效果来看,一个带标识的消息队列,就像多条并存的管道一样。

消息队列实现了对消息发送方和消息接收方的解耦,一个进程在往一个消息队列中写入消息之前,不需要有某个进程在该队列上等待消息到达。使得双方可以异步处理消息数据,这一特点对分布式环境特别有用。

消息队列的使用方法

1.发送者:

A)获取消息队列的 ID号 => 先获取key值(ftok),再用 msgget 获取ID号

int msgid;
msgid = msgget(ftok(".", 1), IPC_CREAT|0666);

B)将数据放入一个附带有标识的特殊的结构体,发送给消息队列。 

struct msgbuf
{// 消息类型(固定)long mtype;// 消息正文(可变)// ...
};

2.接收者:

A)获取消息队列的 ID号

B)将指定标识的消息读出。

当发送者和接收者都不再使用消息队列时,及时删除它以释放系统资源。==> msgctl

1.1 消息队列的创建

//函数原型
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>int msgget(key_t key, int msgflg);

key:键值,全局唯一标识,可由ftok()产生
msgflg:操作模式与读写权限,与文件操作函数open类似,同时也可以指定权限,取值为:
        IPC_CREAT:用来创建一个消息队列
        IPC_EXCL:查询由key指定的消息队列释放存在
        IPC_NOWAIT:之后的消息队列操作都为非阻塞
返回值:消息队列MSG对象ID

1.2 向消息队列发送消息

//函数原型
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

msgqid:MSG对象的ID,由msgget()获取。

msgp:一个指向等待被发送的消息的指针

msgsz:消息正文的长度(单位字节),注意不含类型长度
msgflg:发送选项,一般有:
        0:默认发送模式,在MSG缓冲区已满的情形下阻塞,直到缓冲区变为可用状态
        IPC_NOWAIT:非阻塞读写模式,在MSG缓冲区已满的情形下直接退出函数并设置错误码为EAGAIN

1.3 从消息队列接收消息

//函数原型
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

msgqid:MSG对象的D,由msgget(0获取
msgp:存放消息的内存入口
msgsz:存放消息的内存大小N
msgtyp:欲接收消息的类型,前后要一致
        0:不区分类型,直接读取MSG中的第一个消息
        大于0:读取类型为指定msgtypl的第一个消息
        小于0:读取类型小于等于msgtyp绝对值的第一个具有最小类型的消息。例如当MSG对象中有类型为3、1、5类型消息若干条,当msgtyp为-3时,类型为1的第一个消息将被读取
msgflg:接收选项
        0:默认接收模式,在MSG中无指定类型消息时阻塞
        IPC_ NOWAIT:非阻塞接收模式,在MSG中无指定类型消息时直接退出函数并设置错误码为ENOMSG
        MSG_EXCEPT:读取除msgtyp之外的第一个消息
        MSG_NOERROR:如果待读取的消息尺寸比nsgsz,大,直接切割消息并返回msgsz部分,读不下的部分直接丢弃。
若没有设置该项,则函数将出错返回并设置错误码为E2BG 

1.4 使用msgctl函数显式地删除MSG对象

//函数原型
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>int msgctl(int msgid, int cmd, struct msqid_ds *buf);

msqid:MSG对象ID
cmd:控制命令字
        IPC_STAT:获取该MSG的信息,储存在结构体msqid ds中

        IPC_SET:设置该MSG的信息,储存在结构体msqid ds
        IPC_RMID:立即删除该MSG,并且唤醒所有阻塞在该MSG上的进程,同时忽略第三个参数

2.共享内存 shm

共享内存是通过不同进程共享一段相同的内存来达到通信的目的,共享内存是众多IPC方式最高效的一种方式,一般情况下共享内存是不能单独使用的,需要配合诸如互斥锁、信号量等协同机制使用

像上图所示,当进程 P1 向其虚拟内存中的区域1写入数据时,进程2就能同时在其虚拟内存空间的区域2看见这些数据,中间没有经过任何的转发,效率极高。

使用共享内存的一般步骤

  1. 创建ipc系统唯一标识key -> ftok
  2. 创建共享内存 -> shmget
  3. 映射共享内存 -> shmat
  4. 共享内存读写
  5. 解除共享内存映射 -> shmdt
  6. 删除共享内存 -> shmctl

2.1 创建或打开SHM

//函数原型
#include <sys/ipc.h>
#include <sys/shm.h>int shmget(key_t key, size_t size, int shmflg);

key:SHM对象键值
size:共享内存大小
shmflg:创建模式和权限
        IPC_CREAT:如果ky对应的共享内存不存在,则创建SHM对象
        IPC_EXCL:如果该ky对应的共享内存已存在,则报错
        权限与文件创建open类似,用八进制表示
        SHM HUGETLB
返回值:SHM对象ID 

2.2 获取共享内存地址

        函数shmat()用来获取共享内存的地址,获取共享内存成功后,可以像使用通用内存一样对其进行读写操作。

//函数原型
#include <sys/types.h>
#include <sys/shm.h>void *shmat (int shmid, const void *shmaddr, int shmflg);

shmid:指定的共享内存的ID
shmaddr:指定映射后的地址,因为是虚拟地址,分配的原则要兼顾诸如段对齐、权限分配等问题,因此用户进程是无法指定的,只能由系统自动分配,因此此参数一般为NU儿L,表示交由系统来自动分配
shmflg:可选项
        0:默认,代表共享内存可读可写
        SHM_RDONLY:代表共享内存只读
返回值:共享内存映射后的虚拟地址入口 

2.3 解除映射

//函数原型
#include <sys/types.h>
#include <sys/shm.h>int shmdt(const void *shmaddr);

使用完SHM对象后,需要将其跟进程解除关联关系,即解除映射

2.4 共享内存控制函数

//函数原型
#include <sys/types.h>
#include <sys/shm.h>int shmctl(int shmid, int cmd, struct shmid ds *buf);

删除SHM对象,释放内存

shmid:指定的共享内存的ID
cmd:一些命令字
        IPC_STAT:获取共享内存的一些信息,放入shmid_ds{.}中
        IPC_SET:将buf中指定的信息,设置到本共享内存中
        IPC_RMID:删除指定的共享内存,此时第三个参数buf将被忽略
buf:用来存放共享内存信息的结构体 

3. 信号量 sem

信号量SEM全称Semaphore,中文也翻译为信号灯,作为Systemc-V IPC其中一种,信号量与消息队列MSG和共享内存SHM有极大的不同,SEM不是用来传输数据的,而是用来协调进程或者线程工作的,像是一种旗语。

Linux 中用到的信号量有3种:ststem-V 信号量、POSIX有名信号量和 POSIX无名信号量。他们虽然有很多显著不同的地方,但是最基本的功能室一致的:用来表征一种资源的数量,当多个进程或者线程争夺这些稀缺资源的时候,信号量用来保证他们合理地、秩序地使用这些资源,而不会陷入逻辑谬误之中。信号量机制是一种有效的进程同步和互斥工具,

3.1 基本概念

  • 临界资源(Critical Resources):多个进程或线程有可能同时访问的资源
  • 临界区(critical zone):访问这些资源的代码称为临界代码,这些代码区域称为临界区
  • P操作:程序进入临界区之前必须对资源进行申请,这个动作称为P操作
  • V操作:程序离开临界区之后必须释放相应的资源,这个动作称为V操作

3.2 P/V操作

PV操作就是荷兰语Passeren(通过),Vrijgeven(释放)的简称。对应的就是 wait 等待,signal 释放操作。

P操作:S=S-1,若S≥0,进程继续执行;若S<0,进程暂停执行,进入等待队列。即执行P操作时,有可用资源则继续执行,无可用资源测等待。

V操作:S=S+1,若S>0,进程继续执行;若S≤0,唤醒等待队列中的一个进程。即执行V操作时,无等待进程则继续执行,有等待进程则唤醒该进程,然后本进程继续执行。

进程的互斥:指当一个进程进入临界区使用临界资源时,需要使用临界资源的其他进程必须等待。退出临界区后,需要使用该临界资源的进程解除阻塞。互斥是进程之间的间接制约关系

设置信号量初值为0,如果进程A先执行到L1,执行P操作后信号量小于0,A等待,直到进程B执行到L2执行V操作后信号量为0唤醒A继续执行。

如果进程B先执行到L2(信号量+1)则进程A无需等待,直接就可以执行完。这样就实现了通过信号量控制进程的同步

3.3 核心API及实现步骤

  1. 获取共享内存key值 ==> ftok
  2. 获取共享内存ID号 ==> shmget
  3. 共享内存映射 ==> shmat
  4. 获取信号量key值 ==> ftok
  5. 获取信号量ID ==> semget
  6. 初始化信号量的值 ==> semctl
  7. 信号量的P/V操作

1)申请key值。

key = ftok(".",10);

2)根据key值申请信号量ID号。

//函数原型
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>int semget(key_t key, int nsems, int semflg);

key: 信号量的key值

nsems: 信号量元素的个数。例如: 时间+空间 -> 2

semflg: IPC_CREAT|0666 -> 不存在则创建

返回值:

        成功: 信号量ID

        失败: -1

3)控制/设置 信号量值参数。

//函数原型
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>int semctl(int semid, int semnum, int cmd, ...);

semid:信号量ID

semnum:需要操作的成员的下标 时间:0 空间:1

cmd:

        SETVAL      -> 用于设置信号量的起始值

        IPC_RMID     -> 删除信号量的ID

... : 空间/数据的起始值

返回值

        成功:0

        失败:-1

例如: 想设置空间的起始值为1,数据的起始值为0
semctl(semid,0,SETVAL,1);
semctl(semid,1,SETVAL,0);

4)如何实现信号量的P/V操作? (P操作: 1->0 V操作: 0->1

//函数原型
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>int semop(int semid, struct sembuf *sops, size_t nsops);

semid: 信号量ID号

sops:进行P/V操作结构体

nsops: 信号量操作结构体的个数 -> 1

返回值

        成功:0

        失败:-1

//sops:进行P/V操作结构体
struct sembuf
{unsigned short sem_num;   //需要操作的成员的下标  时间:0  空间:1short          sem_op;    //P操作/V操作           P: -1  V: 1short          sem_flg;   //普通属性,填0.
}

 

上面是有关进程通信中 System V IPC 的相关介绍,下篇博客会给出一些示例代码!

如果喜欢请不吝给予三连支持!

小海编程心语录-CSDN博客

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

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

相关文章

科技查新是什么?一文了解!

本文主要解答 1、什么是科技查新&#xff1f; 2、科技查新有哪些作用&#xff1f; 3、科技查新一般应用于什么地方&#xff1f; 4、在哪能出具正规查新报告&#xff1f; 5、科技查新流程是怎样的&#xff1f; 带着这些问题阅读这篇文章相信一定会有收获&#xff01;干活内…

【启程Golang之旅】运算符与流程控制讲解

欢迎来到Golang的世界&#xff01;在当今快节奏的软件开发领域&#xff0c;选择一种高效、简洁的编程语言至关重要。而在这方面&#xff0c;Golang&#xff08;又称Go&#xff09;无疑是一个备受瞩目的选择。在本文中&#xff0c;带领您探索Golang的世界&#xff0c;一步步地了…

如何让UE4.26使用VS2022【Windows,源码下载】

使用UE5一直用的是VS2022&#xff0c;都是因为团队需要&#xff0c;只能用UE4&#xff0c;而我电脑中拥有的UE4的版本是UE4.26以及VS2022&#xff0c;我不可能去下载VS2019来为这么一个项目&#xff0c;所以就研究了一下是哪里阻止了UE4.26不让我使用VS2022. 首先下载UE4.26源码…

记一次安卓“Low on memory“崩溃问题

前言 最近再调人脸识别算法相关demo,发现调试期间总是偶发性崩溃&#xff0c;捕获不到异常的那种&#xff0c;看日志发现原因是Low on memory&#xff0c;一开始还疑惑 App内存不够应该是OOM啊,怎么会出现这种问题&#xff0c;百思不得其解&#xff0c;直到我打开了 Android s…

在MySQL数据库中进行连接查询中的外连接查询

左外连接 特征&#xff1a;以左表为主&#xff0c;显示左表所有数据&#xff0c;相关联存在相同的值时显示对应数据&#xff0c;否则显示为NULL 语法&#xff1a;> select 表名.字段名称&#xff0c;表名.字段名称 from 表名 left join 表名 on 相关联的字段…

Linux java jni调用C++封装动态库

由于项目中java需要调用第三方提供的C动态库&#xff1b;由于第三方动态库传入的参数较多&#xff0c;还伴随着指针传入操作&#xff0c;导致java调用极为不便&#xff01;因此催生出对于第三方的C动态库进行二次封装。java调用只需按结构传入一个结构化的string即可。话不多说…

卧槽!这项目开源了!【送源码 】

随着科技的飞速发展&#xff0c;个人财务管理变得越来越重要。一个名为‘Maybe’的创新型个人财务与财富管理应用程序随之诞生&#xff0c;它以其丰富的功能和用户友好的界面受到了广大用户的关注。 现在项目方将这个价值 100万美元的个人理财应用项目开源了 Maybe Maybe应用…

吴恩达2022机器学习专项课程C2W2:2.19 sigmoid函数的替代方案 2.20如何选择激活函数 2.21 激活函数的重要性

这里写目录标题 引言sigmoid激活函数的局限1.回顾需求案例2.ReLU激活函数 常用的激活函数1.线性激活函数的解释 如何选择激活函数&#xff1f;1.选择输出层的激活函数2.选择隐藏层的激活函数 选择激活函数的总结1.输出层总结2.隐藏层总结3.TensorFlow设置激活函数 激活函数多样…

AI生成视频解决方案,降低成本,提高效率

传统的视频制作方式往往受限于高昂的成本、复杂的拍摄流程以及硬件设备的限制&#xff0c;为了解决这些问题&#xff0c;美摄科技凭借领先的AI技术&#xff0c;推出了全新的AI生成视频解决方案&#xff0c;为企业带来前所未有的视觉创新体验。 一、超越想象的AI视频生成 美摄…

大模型时代的具身智能系列专题(四)

google deepmind团队 谷歌旗下最大的两个 AI 研究机构——地处伦敦 DeepMind 与位于硅谷的 Google Brain 合并成立新部门 Google DeepMind。其将机器学习和系统神经科学的最先进技术结合起来&#xff0c;建立强大的通用学习算法。代表作有AlphaGo&#xff0c;AlphaStar&#x…

鸿蒙ArkTS声明式开发:跨平台支持列表【组件快捷键事件】

组件快捷键事件 开发者可以设置组件的自定义组合键&#xff0c;组合键的行为与click行为一致&#xff0c;组件在未获得焦点状态下也可以响应自定义组合键&#xff0c;每个组件可以设置多个组合键。 说明&#xff1a; 开发前请熟悉鸿蒙开发指导文档&#xff1a; gitee.com/li-s…

香橙派 AiPro通过Micro USB接口进行串口调试

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、配置步骤1.安装CH343驱动2.配置串口参数 二、使用步骤总结 前言 最近在玩一个新玩具香橙派 AiPro&#xff0c;除了通过SSH方式连接开发板以外&#xff0c;…

华为机考入门python3--(32)牛客32-密码截取

分类&#xff1a;最长对称子串、动态规划 知识点&#xff1a; 生成二维数组 dp [[0] * n for _ in range(n)] 求最大值 max(value1, value2) 动态规划的步骤 a. 定义问题 长度为n下最长的对称子串的长度 b. 确定状态 dp[i][j]表示字符串从索引i到j的子串是否为对称…

封装,static,代码块,对象的打印

封装&#xff0c;static&#xff0c;代码块&#xff0c;对象的打印 1. 封装1.1 封装的概念1.2 包的概念1.3 访问修饰限定符1.4 被封装的属性如何set和get&#xff1f; 2. static2.1 再谈学生类2.2 static修饰成员变量2.3 static修饰成员方法2.4 static成员变量初始化 3. 代码块…

IGMP——组播成员端网络协议

目录 一.IGMP基本概念 &#xff08;1&#xff09;组播转发困境 &#xff08;2&#xff09;感知组播成员方式 &#xff08;3&#xff09;IGMP版本 二.IGMP各版本的区别与联系 &#xff08;1&#xff09;IGMPV1 1.普遍组查询报文 2.成员关系报告报文 3.IGMPV1报文格式 4…

java第十七课 —— 递归

方法递归调用 递归就是方法自己调用自己&#xff0c;每次调用时传入不同的变量&#xff0c;递归有助于编程者解决复杂问题&#xff0c;同时可以让代码变得简洁。 递归重要规则 执行一个方法时&#xff0c;就创建一个新的受保护的独立空间&#xff08;栈空间&#xff09;。方…

922. 按奇偶排序数组 II - 力扣

1. 题目 给定一个非负整数数组 nums&#xff0c; nums 中一半整数是 奇数 &#xff0c;一半整数是 偶数 。 对数组进行排序&#xff0c;以便当 nums[i] 为奇数时&#xff0c;i 也是 奇数 &#xff1b;当 nums[i] 为偶数时&#xff0c; i 也是 偶数 。 你可以返回 任何满足上述…

微服务架构-异步消息传递设计模式

微服务架构-异步消息传递设计模式 异步消息允许服务发送消息后立即返回&#xff0c;而不需要等待消息被处理完毕&#xff0c;这种异步方式可以大大提高系统的处理速度、和吞吐量。 微服务架构&#xff0c;通常涉及多个服务之间的相互调用&#xff0c;如果通信只是在少数几个微…

lama-cleaner中的Paint-by-Example使用

Lama Cleaner是一个免费的、开源的、完全自托管的修复工具&#xff0c;里面提供了很多最前沿的AIGC模型。可以使用它从图片中删除任何不需要的物体、缺陷、人物&#xff0c;或删除和替换图片上的任何内容。本文章详细介绍了该工具的所有功能&#xff0c;并体验了下每个功能的实…

Shell编程之正则表达式与文本处理器

一、正则表达式 之前学习了 Shell 脚本的基础用法&#xff0c;已经可以利用条件判断、循环等语句编辑 Shell 脚本。接下来我们将开始介绍一个很重要的概念——正则表达式&#xff08;RegularExpression&#xff0c;RE&#xff09;。 1.1正则表达式概述 下面先来了解一下正则表…