Linux---进程间通信(下)

1、System V 共享内存

原理如下图

 系统调用接口介绍

int shmget(key_t key, size_t size, int shmflg)

功能:用来创建共享内存
参数

  • key:这个共享内存段名字,内核用key来标识共享内存
  • size:共享内存大小
  • shmflg:由九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样的(这里介绍两个:IPC_CREAT和IPC_EXCL,其中IPC_CREAT表示共享内存存在就返回,不存在就创建,IPC_EXCL不单独使用,IPC_EXCL | IPC_CREAT表示不存在就创建,存在就出错返回,作用是确保创建出来的共享内存一定是全新的)

返回值:成功返回一个非负整数,即该共享内存段的标识码(作用类似文件描述符fd);失败返回-1

void* shmat(int shmid, const void* shmaddr, int shmflg)

功能:将共享内存段连接到进程地址空间(在页表中创建映射关系)
参数

  • shmid:共享内存标识
  • shmaddr:指定连接的地址(可以直接传nullptr,让OS帮你分配)
  • shmflg:它的两个可能取值是SHM_RND和SHM_RDONLY

返回值:成功返回一个指针,指向共享内存第一个节(类比malloc);失败返回-1

 int shmdt(const void *shmaddr)

功能:将共享内存段与当前进程脱离(删除页表中的映射关系)
参数

  • shmaddr:由shmat所返回的指针

返回值:成功返回0;失败返回-1
注意:将共享内存段与当前进程脱离不等于删除共享内存段

int shmctl(int shmid, int cmd, struct shmid_ds *buf)

功能:用于控制共享内存
参数

  • shmid:由shmget返回的共享内存标识码
  • cmd:将要采取的动作(IPC_STAT---获取共享内存的相关信息、IPC_SET---设置共享内存的相关信息、IPC_RMID---释放共享内存)
  • buf:指向一个保存着共享内存的模式状态和访问权限的数据结构

返回值:成功返回0;失败返回-1

(共享内存的生命周期是随内核的,即进程结束,共享内存不会释放,需要手动释放空间)

 共享内存的通信代码如下

//comm.hpp#include <string>
#include <iostream>
#include <sys/ipc.h>
#include <unistd.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <cstring>
using namespace std;// 路径和项目id可以随便写,但是建议写和代码相关的
string pathname = "/shm";
int process_id=0x11223344;const int size = 4096; // 建议设置为n*4096,Linux以4096为单位进行分配共享内存
string filename = "fifo"; //管道名,下面代码用管道是利用管道的同步机制,共享内存没有同步机制key_t Getkey()
{key_t key = ftok(pathname.c_str(), process_id);// 该系统调用相当于一个hash函数,用两个参数通过算法获得一个hash值 keyif(key < 0){cout << "errno: " << errno << ",errstring: " << strerror(errno) << endl;exit(1);}return key;
}string ToHex(int id) // 返回16进制表示形式 
{char buffer[1024];snprintf(buffer,sizeof(buffer),"0x%x",id);return buffer;
}int CreateShmHelper(key_t key, int flag)
{int shmid = shmget(key, size, flag);if(shmid < 0){cout << "errno: " << errno << ",errstring: " << strerror(errno) << endl;exit(2);}return shmid;
}int GetShm(key_t key)
{return CreateShmHelper(key, IPC_CREAT);
}int CreateShm(key_t key)
{return CreateShmHelper(key, IPC_CREAT|IPC_EXCL|0666);// 设置创建共享内存并设置权限0666---八进制
}//server.cc#include "comm.hpp"
//用一个类来初始化资源和释放资源
class Init
{
public:Init(){int n = mkfifo(filename.c_str(), 0666);if(n < 0) exit(1);key_t key = Getkey();cout << "key:" << ToHex(key) << endl;// sleep(5);// key vs shmid// key:内核中使用,标识共享内存的唯一性// shmid:应用这个共享内存的时候,我们使用shmid来使用操作共享内存// 即key是给内核看的,shmid是给用户看的shmid = CreateShm(key);cout << "shmid:" << shmid << endl;cout << "创建内存" << endl;p = (char*)shmat(shmid, nullptr, 0);cout << "将内存挂接到虚拟地址空间" << endl;sleep(3);
//注意资源的初始化顺序,管道的打开要放在恰当的地方,不然会出bug,这边建议放到最后fd = open(filename.c_str(), O_RDONLY);// 读端}~Init(){close(fd);unlink(filename.c_str());// 删除管道文件shmdt(p);cout << "删除页表映射" << endl;sleep(3);shmctl(shmid, IPC_RMID, nullptr);cout << "删除内存" << endl;}
public:int fd;int shmid;char*p;
};int main()
{Init init;int code = 0;while(1){ssize_t n = read(init.fd, &code, sizeof(code));if(n > 0){cout << "client:" << init.p << endl;}else if(n == 0){break;}}return 0;
}//client.cc
#include "comm.hpp"int main()
{key_t key = Getkey();cout << "key:" << ToHex(key) << endl;int shmid = GetShm(key);cout << "获取shmid:" << shmid << endl;char *p = (char *)shmat(shmid, nullptr, 0); // 开出来的空间当数组用即可cout << "挂接" << endl;int fd = open(filename.c_str(), O_WRONLY);int code = 1;cout << "write start" << endl;for (int i = 0; i < 26; i++){p[i] = 'a' + i;sleep(2);write(fd, &code, sizeof(code));cout << "write:" << (char)('a' + i) << endl;}shmdt(p);cout << "取消映射" << endl;return 0;
}

在看完上面这段代码的前提下,我们就能解释两个进程如何得到同一个共享内存的标识符:本质是我们事先约定了标识符key的值(在上面的代码中,我们是用ftok函数生成的key,使用的相同的参数,所以返回值也相同。这里使用ftok只是让系统帮助我们生成key,其实只要key这个值相对其他共享内存的key是唯一的即可),放在头文件中,然后两个程序通过key就能找到同一个共享内存

特点:

  • 共享内存的通信方式,不会提供同步机制,共享内存是直接裸露给所有的使用者的,一定要注意共享内存的使用安全问题
  • 共享内存可以提供较大的空间
  • 共享内存是所有进程间通信速度最快的(因为管道底层是对文件操作的复用,所以数据需要在用户缓冲区和内核文件缓冲区间来回拷贝,但是共享内存不需要,共享内存可以理解为用malloc申请了一块空间,两个进程都能看见,没有用户缓冲区和内核文件缓冲区来回拷贝的过程,所以更快)

查看管理ipc资源的指令介绍

 ipcs -m

ipcrm -m shmid   删除共享内存

2、System V 消息队列---简单介绍

消息队列提供一个进程给另一个进程发送数据块的能力

3、System V信号量---简单介绍

背景介绍

当我们在进行进程间通信的时候,可能会出现A进程和B进程通过同一份资源在进行通信,突然C进程也开始往该资源中写数据/读数据,导致数据传输出现问题的情况,换句话说,当多执行流访问同一份资源时,我们需要保护该资源,所以我们有了信号量这个概念

在介绍信号量的概念之前,我们先来看看信号量(semaphore)的系统调用接口

信号量的概念和理解

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

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

相关文章

软件游戏显示d3dx9_42.dll丢失的5种解决方法,快速解决dll问题

当计算机系统中d3dx9_42.dll文件丢失时&#xff0c;可能会引发一系列运行问题和功能异常&#xff0c;具体表现形式多样且影响范围较广。首先&#xff0c;对于依赖于DirectX 9.0c版本的各类应用程序&#xff0c;尤其是部分经典的老款游戏&#xff0c;由于d3dx9_42.dll是其中不可…

云原生之API网关Traefik

1. 前言 说到web服务的开源网关&#xff0c;我首先想到的是Nginx&#xff0c;最早使用的就是它&#xff0c;现在都还在使用它。系统上线了Docker Swarm集群之后&#xff0c;不继续使用Nginx直接做Docker服务的网关&#xff0c;是因为Nginx毕竟比Docker Swarm出现的早&#xff0…

用Python实现创建十二星座数据分析图表

下面小编提供的代码中&#xff0c;您已经将pie.render()注释掉&#xff0c;并使用了pie.render_to_file(十二星座.svg)来将饼状图渲染到一个名为十二星座.svg的文件中。这是一个正确的做法&#xff0c;如果您想在文件中保存图表而不是在浏览器中显示它。 成功创建图表&#xf…

图解目标检测 之 【YOLOv9】 算法 最全原理详解

YOLOv9与SOTA模型对比 什么是 YOLOv9&#xff1f;YOLOv9是YOLO系列中的最新产品&#xff0c;是一种实时目标检测模型。它通过先进的深度学习技术和架构设计&#xff0c;包括通用 ELAN (GELAN) 和可编程梯度信息 (PGI)&#xff0c;展现出更好的性能。 YOLO 系列通过引入计算机视…

数据结构知识点总结-绪论 数据结构基本术语 算法及评价

要求 &#xff08;1&#xff09;对数据结构这么课学了哪些知识有个清楚的认知&#xff1b; &#xff08;2&#xff09;掌握目录结构&#xff0c;能复述出来每个知识点下都有哪些内容。 如下图所示&#xff0c;可自行制作思维导图&#xff0c;针对自己薄弱的地方进行复习。 …

Gitflow:一种依据 Git 构建的分支管理工作流程模式

文章目录 前言Gitflow 背景Gitflow 中的分支模型Gitflow 的版本号管理简单模拟 Gitflow 工作流 前言 Gitflow 工作流是一种版本控制流程&#xff0c;主要适用于较大规模的团队。这个流程在团队中进行合作时可以避免冲突&#xff0c;并能快速地完成项目&#xff0c;因此在很多软…

14. UE5 RPG使用GameplayTag

GameplayTag本来是应用在GAS游戏技能系统里面的&#xff0c;后来UE直接将其抽离出来&#xff0c;作为一个模块&#xff0c;现在可以不在GAS里也可以使用这个模块。比如&#xff0c;我需要判断一个射线拾取的物体&#xff0c;首先我需要判断这个actor是否存在&#xff0c;然后判…

1906_ AMBA_高级MCU总线架构

1906_ AMBA_高级MCU总线架构 全部学习汇总&#xff1a; g_arm_cores: ARM内核的学习笔记 (gitee.com) 在看内核相关的文件的时候看到了AMBA这个缩写&#xff0c;查了一下具体的概念。这个其实是一个总线架构&#xff0c;应该是ARM设计的。我找到了相关的介绍网页&#xff1a; A…

Webserver解决segmentation fault(core dump)段错问问题

前言 在完成了整个项目后&#xff0c;我用make命令编译了server&#xff0c;当我运行./server文件时&#xff0c;出现了段错误 在大量的代码中找出错因并不是一件容易的事&#xff0c;尤其是对新手程序员来说。而寻找bug的过程就像是侦探调查线索追查凶手一样&#xff0c;我们…

找游戏 - 华为OD统一考试(C卷)

OD统一考试&#xff08;C卷&#xff09; 分值&#xff1a; 200分 题解&#xff1a; Java / Python / C 题目描述 小扇和小船今天又玩起来了数字游戏&#xff0c; 小船给小扇一个正整数 n&#xff08;1 ≤ n ≤ 1e9&#xff09;&#xff0c;小扇需要找到一个比 n 大的数字 m&a…

*MYSQL--索引--内部原理

MYSQL的索引根据功能,主要有三大类型: 1.HASH索引 2.二叉树 3.BTREE索引 一:HASH索引 1.内部原理: 在设置了某列为索引列之后,并且开始或者将要在相应索引列创建数据的时候,系统通过某种算法 F(X) 自动计算出来一个十六进制的哈希值,这个哈希值能够对应相应的字段值 所以…

QFileDialog文件选择对话框

QFileDialog 类是 Qt 框架中用于处理文件对话框的一个类&#xff0c;它继承自 QDialog。QFileDialog 提供了标准的文件选择对话框&#xff0c;使用户能够选择文件或目录。这个类可以用于打开或保存文件&#xff0c;也可以用来选择目录。 主要功能 打开和保存文件&#xff1a;…