【Linux】进程间通信之共享内存

🤖个人主页:晚风相伴-CSDN博客

💖如果觉得内容对你有帮助的话,还请给博主一键三连(点赞💜、收藏🧡、关注💚)吧

🙏如果内容有误的话,还望指出,谢谢!!!

目录

✨理解进程间通信的本质

共享内存

✨共享内存如何实现进程间通信

🔥共享内存示意图

🔥认识共享内存函数

 shmget函数

ftok函数

 shmat函数

shmdt函数

代码实现共享内存

🔥查看共享内存的信息的命令

✨结论 

完整代码链接


✨理解进程间通信的本质

因为进程具有独立性,所以每个进程都只知道自己,而不知道有另外的进程存在,所以要实现不同进程间的通信,就要让不同的进程都能看到同一块资源,这块资源不属于任意一个进程,而是强调共享,利用这块资源就可以实现进程间通信了。

总结一下要点 

  1. 进程间通信的前提是要让不同的进程看到同一块资源
  2. 这一块资源不隶属于任何一个进程,而是被这些进程所共享 

System V分类

  • 消息队列
  • 共享内存
  • 信号量 

共享内存

进程间通信的方式之一是System V,共享内存是System V通信中的一种。共享内存是最快的进程间通信的方式。

✨共享内存如何实现进程间通信

通信的前提:要让不同进程间实现通信就需要让不同的进程都能看到同一块资源。

实现过程如下

  1. 一个进程在物理内存中申请一块空间,并且通过页表映射到自己的地址空间中的共享区
  2. 不同的进程也将这块空间通过页表映射到各自的地址空间中的共享区,这就实现了不同的进程看到了同一块资源
  3. 那么进程就可以找到自己的地址空间中的共享区访问共享内存,当一个进程往当一个进程往这块共享内存写入数据时,其它进程访问这块共享内存就可以读取到数据,从而实现了进程间的通信。

🔥共享内存示意图

🔥认识共享内存函数

 shmget函数

功能:用来创建共享内存

参数

  • key:是一个整形,key值相同的进程才能看到同一块共享内存,就好比共享内存是一把锁,而key是钥匙,只有拿到相同钥匙的进程才能打开这把共享内存这把锁。
  • size:是这个共享内存的大小。
  • shmflg:创建方式。和open函数里的flags用法是类似的,一共有9个。主要介绍IPC_CREAT和IPC_EXCL。IPC_CREAT单独使用,创建共享内存时,如果底层已经存在,获取之;如果底层不存在,创建之并返回。IPC_EXCL单独使用没有意义。IPC_CREAT和IPC_EXCL一起使用,创建共享内存时,如果底层已经存在,出错返回;如果底层不存在创,建之并返回。

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

ftok函数

功能:利用给定的pathname和proj_id通过底层的算法来生成key值

参数

  • pathname:给定的一个路径(你必须有这个路径的权限)
  • proj_id:有效的8位二进制数

返回值:成功返回key值,失败返回-1

 shmat函数

功能:将指定的共享内存挂接到自己的地址空间(也就是建立映射)

参数

  • shmid:共享内存的标识码
  • shmaddr:指定挂接的地址,一般设为nullptr,让操作系统自动选择
  • shmflg:暂时用不上设置为0

返回值:返回一个指向共享内存的指针,失败返回-1

shmdt函数

功能:将指定的共享内存,从自己的地址空间中去关联

参数:由shmat返回的指针

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

shmctl函数

功能:控制共享内存

参数

  • shmid:共享内存标识码
  • cmd:设置为IPC_RMID表示删除共享内存
  • buffer:指向一个保存着共享内存的模式状态和访问控制的数据结构,暂时用不到设置为nullptr

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

代码实现共享内存

log.hpp

#pragma once#include <iostream>
#include <string>
#include <ctime>
#include <cstdio>
#include <cstdarg>// 日志级别
#define DEBUG 0
#define NORMAL 1
#define WARNING 2
#define ERROR 3
#define FATAL 4const char *gLevelMap[] = {"DEBUG","NORMAL","WARNING","ERROR","FATAL"
};#define LOGFILE "./threadpool.log"void logMessage(int level, const char *format, ...)
{//调试小技巧
#ifndef DEBUG_SHOWif (level == DEBUG)return;
#endifchar stdBuffer[1024]; // 标准部分time_t timestamp = time(nullptr);snprintf(stdBuffer, sizeof stdBuffer, "[%s][%ld]", gLevelMap[level], timestamp);char logBuffer[1024]; // 自定义部分va_list args;va_start(args, format);// vprintf(format, args);vsnprintf(logBuffer, sizeof logBuffer, format, args);va_end(args);//写入文件中//FILE* fp = fopen(LOGFILE, "a");//fprintf(fp, "%s%s\n", stdBuffer, logBuffer);//fclose(fp);printf("%s%s\n", stdBuffer, logBuffer);
}

comm.hpp

#pragma once#include <iostream>
#include <cstdio>
#include <cassert>
#include <cstring>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "log.hpp"using namespace std;#define PATH_NAME "/home/hjx"
#define PROJ_ID 0x66
#define SHM_SIZE 4096 //共享内存的大小,最好是页的整数倍

shmclient.cc 

#include "comm.hpp"int main()
{logMessage(NORMAL, "client pid: %d", getpid());//日志信息,可去掉//获取key值key_t key = ftok(PATH_NAME, PROJ_ID);if (key < 0){logMessage(ERROR, "create key fail");exit(1);}logMessage(NORMAL, "create key success, client key: %d", key);// 创建共享内存int shmid = shmget(key, SHM_SIZE, IPC_CREAT); // 0666权限if (shmid < 0){logMessage(ERROR, "create shmget fail");exit(2);}logMessage(NORMAL, "create shmget success, shmid: %d", shmid);// 与地址空间建立关联char *shmaddr = (char *)shmat(shmid, nullptr, 0);if (shmaddr == nullptr){logMessage(ERROR, "create shmat fail");exit(3);}logMessage(NORMAL, "attach shmat success, shmid: %d", shmid);// 写入数据while(true){char buffer[1024];cout << "say >";cin >> buffer;if(strcmp(buffer, "quit") == 0) break;snprintf(shmaddr, SHM_SIZE - 1,  "hello server, 我正在和你通信, pid: %d, client say > %s\n", getpid(), buffer);}strcpy(shmaddr, "quit");// 去除与地址空间的关联int n = shmdt(shmaddr);assert(n != -1);(void)n;logMessage(NORMAL, "detach shmdt success, shmid: %d", shmid);return 0;
}

shmserver.cc

#include "comm.hpp"int main()
{// 创建公共的key值key_t key = ftok(PATH_NAME, PROJ_ID);assert(key != -1);logMessage(NORMAL, "create key finish, server key: %d", key);// 创建一个全新的共享内存int shmid = shmget(key, SHM_SIZE, IPC_CREAT | IPC_EXCL | 0666); // 0666权限if (shmid == -1){perror("shmget");exit(1);}logMessage(NORMAL, "create shmid finish, shmid: %d", shmid);// 将指定的共享内存挂接到自己的地址空间(建立映射)char *shmaddr = (char *)shmat(shmid, nullptr, 0);logMessage(NORMAL, "attach shm finish, shmid: %d", shmid);// sleep(10);// 读取数据for (;;){printf("%s\n", shmaddr);if(strcmp(shmaddr, "quit") == 0) break;sleep(1);}// 将指定的共享内存,从自己的地址空间中去关联int n = shmdt(shmaddr);assert(n != -1);(void)n;logMessage(NORMAL, "detach shm finish, shmid: %d", shmid);// 删除共享内存int m = shmctl(shmid, IPC_RMID, nullptr);assert(m != -1);(void)m;logMessage(NORMAL, "create shmid finish, shmid: %d", shmid);return 0;
}
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

结果演示: 

🔥查看共享内存的信息的命令

可以使用ipcs -m命令查看共享内存的信息

  • key:我们代码打印出来的key值是十进制,转换为十六进制就是上面的值,key是唯一的可用来标识一块共享内存
  • shmid:共享内存的标识码,和key值一样都可以标识一块共享内存
  • bytes:这块共享内存的大小,可以把共享内存看做是一个很大的数组或字符串
  • nattch:表示有多少个进程和这块地址空间进行了关联

也可以使用ipcrm -m命令删除共享内存

✨结论 

  1. 只要是使用了共享内存进行通信,一个进程向共享内存中写入数据,另一个进程立马就可以看到对方写入的数据,共享内存是所有进程间通信中速度最快的,因为它不经过系统调用也就不需要过多的拷贝
  2. 在上面的结果演示中,可以看到当我们client端还未跑起来时,我们的server端就已经在那里读取数据了,因此可以得出结论,共享内存缺乏访问控制,并且会带来并发问题,但是如果我们想让它拥有访问控制也是可以的,只需要把它和管道结合起来就行了。

加入管道之后结果演示: 

完整代码链接

 共享内存

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

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

相关文章

【Linux系统编程】第十六弹---冯诺依曼体系结构与操作系统

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】 目录 1、冯诺依曼体系结构 2、操作系统原理 2.1、什么是操作系统&#xff1f; 2.2、用图解释操作系统 2.3、理解操作系统 总结 …

QT的TcpServer

Server服务器端 QT版本5.6.1 界面设计 工程文件&#xff1a; 添加 network 模块 头文件引入TcpServer类和TcpSocket&#xff1a;QTcpServer和QTcpSocket #include <QTcpServer> #include <QTcpSocket>创建server对象并实例化&#xff1a; /*h文件中*/QTcpServer…

NAND Flash 与 NOR Flash间的区别

非易失性存储器是一种即使未通电也能保持其内容的存储器。非易失性存储器可以有不同的形式: ROM – 只读存储器&#xff0c;数据写入一次&#xff0c;允许多次读取访问。 PROM – 可编程只读存储器&#xff0c;数据写入一次&#xff08;不是在制造过程中&#xff0c;而是以后的…

【论文速读】| LLM4FUZZ:利用大语言模型指导智能合约的模糊测试

本次分享论文&#xff1a;LLM4FUZZ: Guided Fuzzing of Smart Contracts with Large Language Models 基本信息 原文作者&#xff1a;Chaofan Shou, Jing Liu, Doudou Lu, Koushik Sen 作者单位&#xff1a;加州大学伯克利分校&#xff0c;加州大学欧文分校&#xff0c;Fuzz…

15 华三华为链路聚合综述

1 链路聚合简介 以太网链路聚合通过将多条以太网物理链路捆绑在一起形成一条以太网逻辑链路&#xff0c;实现增加链路带宽的目的&#xff0c;同时这些捆绑在一起的链路通过相互动态备份&#xff0c;可以有效地提高链路的可靠性。 2 成员端口的状态 聚合组内的成员端口具有以下…

2024年,Web开发新趋势!

随着我们迈入新的一年&#xff0c;现在正是审视2024年网页开发领域开始流行哪些趋势的绝佳时机。回顾2023年的一系列更新&#xff0c;以下是来年一些热门话题的概览。 自主托管有回归的趋势 近些年&#xff0c;自主托管一直是网页开发者和公司托管其应用程序的默认方式。开发…

蓝桥杯13届JAVA A组 国赛

​​​​​​​ package 蓝桥杯国赛; // 贪心选个数最少的进行摆 // 2:1 ,3:1, 4:1,5 : 3,6:3,7:1 // 选 1&#xff0c;7&#xff0c;4&#xff0c;2&#xff0c;3&#xff0c;5&#xff0c;9 // 然后都选满10个 public class 火彩棒数字 {public static void main(String[] a…

游戏行业被攻击的原因、攻击种类及合适的服务器

很多游戏刚上线没多久就频繁遭到同行恶意攻击。在相关数据报告中&#xff0c;2023年上半年遭受DDoS攻击的行业中&#xff0c;游戏行业占到40%&#xff0c;而且攻击方式、攻击频率、攻击峰值呈明显上升趋势。很多充满创意的游戏开发公司刚才开发上线一个很有特色的产品&#xff…

安卓实现视频录制与显示和翻转摄像头

权限&#xff1a; <!-- 相机权限 --> <uses-featureandroid:name"android.hardware.camera"android:required"false" /> <uses-permission android:name"android.permission.CAMERA" /><!-- 录音权限&#xff08;包括麦克…

Centos 7.9 配置VNCServer实现远程vnc连接

文章目录 1、Centos安装图形界面1.1、安装X Windows System图形界面1.2、安装GNOME图形界面 2、VNC SERVER配置2.1、VNC SERVER安装2.2、VNC SERVER配置1&#xff09;创建vnc配置文件2&#xff09;修改配置文件内容3&#xff09;完整配置文件参考 2.3、设置vnc密码2.4、配置防火…

网络编程套接字和传输层tcp,udp协议

认识端口号 我们知道在网络数据传输的时候&#xff0c;在IP数据包头部有两个IP地址&#xff0c;分别叫做源IP地址和目的IP地址。IP地址是帮助我们在网络中确定最终发送的主机&#xff0c;但是实际上数据应该发送到主机上指定的进程上的&#xff0c;所以我们不仅要确定主机&…

虚拟化技术 分离虚拟机数据流量与ESXi的流量管理

一、实验内容 为ESXi主机添加网卡通过vClient查看已添加的网卡信息为ESXi添加网络&#xff0c;创建标准交换机修改网络配置&#xff0c;实现虚拟机数据流量与ESXi的管理流量分离 二、实验主要仪器设备及材料 安装有64位Windows操作系统的台式电脑或笔记本电脑&#xff0c;建…

泰达克仿钻点水晶饰品包装印刷防滑UV胶特性及应用场景

仿钻点UV滴胶是一种特殊的胶水 常用于模拟钻石的效果 它是一种透明的胶水 具有高光泽度和折射率 可以在物体表面形成类似钻石的亮闪效果 仿钻点UV滴胶通常由紫外线固化胶组成 需要通过紫外线照射来固化和硬化 它具有以下特点&#xff1a; 1. 透明度&#xff1a;仿钻点UV滴胶具有…

使用 OpenCV 创建视频(74)

返回:OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇:OpenCV 库来捕获和处理视频输入和相似度测量(73) 下一篇&#xff1a;OpenCV使用 Kinect 和其他兼容 OpenNI 的深度传感器(75) 目标 每当您使用视频源时&#xff0c;您最终可能希望将图像处理结果保…

Zabbix6.0容器化部署(Docker-Composed)

Zabbix 为每个 Zabbix 组件提供 Docker image 作为可移植和自给自足的容器&#xff0c;以加快部署和更新过程。 Zabbix 组件在 Ubuntu、Alpine Linux 和 CentOS 基础 image 上提供:Zabbix 组件支持 MySQL 和 PostgreSQL 数据库、Apache2 和 Nginx Web 服务器。 1. Zabbix 组件…

ASP.NET网上车辆档案管理系统

摘 要 本文采用基于Web的Asp.net技术&#xff0c;并与sql server 2000数据库相结合&#xff0c;研发了一套车辆档案管理系统。该系统扩展性好&#xff0c;易于维护。简化了车辆档案设计流程&#xff0c;去除了冗余信息。汽车销售企业可以通过本系统完成整个销售及售后所有档案…

C语言指针的初级练习

前言 从0开始记录我的学习历程&#xff0c;我会尽我所能&#xff0c;写出最最大白话的文章&#xff0c;希望能够帮到你&#xff0c;谢谢。 提示&#xff1a;文章作者为初学者&#xff0c;有问题请评论指正&#xff0c;感谢。 哥们嗷 不知道你和我是否一样在学习C语言指针的时…

【ZZULI数据结构实验】压缩与解码的钥匙:赫夫曼编码应用

&#x1f4c3;博客主页&#xff1a; 小镇敲码人 &#x1f49a;代码仓库&#xff0c;欢迎访问 &#x1f680; 欢迎关注&#xff1a;&#x1f44d;点赞 &#x1f442;&#x1f3fd;留言 &#x1f60d;收藏 &#x1f30f; 任尔江湖满血骨&#xff0c;我自踏雪寻梅香。 万千浮云遮碧…

使用 Docker 部署 TaleBook 私人书籍管理系统

1&#xff09;项目介绍 GitHub&#xff1a;https://github.com/talebook/talebook Talebook 是一个简洁但强大的私人书籍管理系统。它基于 Calibre 项目构建&#xff0c;具备书籍管理、在线阅读与推送、用户管理、SSO 登录、从百度/豆瓣拉取书籍信息等功能。 友情提醒&#x…

工业交换机外壳材质大比拼,看看哪种外壳适合你

在工业领域里&#xff0c;交换机就像我们的网络心脏&#xff0c;时刻跳动着确保信息畅通无阻。而它的外壳&#xff0c;就是保护这颗“心脏”的铠甲。今天&#xff0c;咱们就来聊聊这些铠甲——工业交换机外壳的材质和防护等级&#xff0c;看看它们如何守护我们的网络世界。 首…