【Linux】system V 共享内存(下)

简介: 【Linux】system V 共享内存

1. 创建key值


e77425d60f69484387fc398f47c938a2.png

comm.hpp 公共路径中构建一个函数 Getkey 用于返回key值


5425314557c94fe6a7b74611d186f7f1.png


构建一个函数 tohex,用于将数转换为十六进制


5537743d21a0448487e8e4f3afe305ef.png


通过server.cc与client.cc中分别调用Getkey 与tohex函数


a58a1a217d7b47999e545a5bc18e2681.png


两者的返回值key 是相同的,并且返回的都是十六进制数


2. 创建共享内存 获取共享内存


6775b00a931a44d2bf7c417a79a675a0.png


创建共享内存,调用shmget函数,通过两个选项 若共享内存不存在则创建,若存在则报错

而获取共享内存,调用shmget函数,则返回已有的共享内存


c5bfcb71c23d4823b038b5ec4902bc9e.png

此时运行可执行程序,发现server与client的shmid(共享内存标识符)相同

3. 将自己和共享内存关联起来

输入 man shmat 指令

4b23b2dcffdb4db18394ce6d922f0288.png

at代表 关联

将共享内存和目标值关联起来

返回值为 共享内存的虚拟地址的起始地址

我们不知道应该把共享内存放在虚拟空间的什么地址处,所以shmaddr设为NULL让系统自主去选择

shmflg 可以设置为 SHM_RDONLY 表示当前共享内存是只读的 一般设为0,默认为读写的

4e5997f75fe34fa08b4091f079dd2a8f.png

4. 将自己和共享内存取消关联

输入 man shmdt 指令


c9185451f828442ea0318be447722882.png

shmdt代表 虚拟地址

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

813d452a405743f69e618dad1bd0159a.png

5. 删除共享内存

创建共享内存的进程已经早就退出了,但是共享内存还存在

确认共享内存存在: ipcs

ipc作为进程间通信的简写

ipc表示资源 s表示有多个资源

e9d629efc4b749639e6fd7a241092a06.png

显出来的为ipc通信系统所支持的三种ipc通信策略

Message Queues 消息队列

Shared Memory Segments 共享内存段

Semaphore Arrays 信号量

ipcs - m 查看共享内存段

020dad6ef00d499f84769b3c6d273a55.png

perms 代表权限

bytes 代表字节数

nattch 代表 有几个进程和当前进程是关联的

用指令删除

key是在操作系统中使用的,类似于文件的inode编号

shmid 类似于文件的fd

所以删除操作,是在用户层,应该用shmid

6c8cf20f0687429d9c789b5c3db32a09.png


ipcrm -m shmid值 就可以删除共享内存

此时就没有 shmid为0的共享内存 存在了

调用系统调用

输入 man shmctl 指令


1b95bdbfbbc8482abc3a43bae6f747cd.png

shmid 代表 共享内存描述符 即想对那个共享内存操作

cmd 代表 选项 即想做什么操作

IPC_STAT 获取当前共享内存的属性

IPC_SET 设置共享内存属性

IPC_RMID 标记这个段被释放

buf 代表 共享内存的属性

87f570f004ba4c0da49499faf81c2b8e.png


在comm.hpp下 设置删除共享内存的函数,在server.cc中调用函数 即可删除共享内存

完整代码

makefile

.PHONY:all
all:server client
server:server.cc
  g++ -o $@ $^
client:client.cc
  g++ -o $@ $^
.PHONY:clean
clean:
  rm -f server client 

如何使两个可执行程序运行,在上一篇文章提到过,点击查看:命名管道


comm.hpp

#ifndef _COMM_HPP_
#define _COMM_HPP_
#include<iostream>
#include<cerrno>
#include<cstdio>
#include<cstring>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/types.h>
#include<assert.h>
using namespace std;
#define PATHNAME "."//.表示当前路径  路径字符串
#define PROJID 0x6666 //项目id
const int gsize=4096;
key_t getkey()//用于返回key值
{
    key_t k=ftok(PATHNAME,PROJID);
    if(k==-1)//失败
    {
       cout<<errno<< " :" <<strerror(errno)<<endl;
       exit(1);
    }
    return k;//返回key值
}
string tohex(int x)//转换为十六进制
{
   char buffer[64];
   //将x以十六进制的形式传给buffer
   snprintf(buffer,sizeof(buffer),"0x%x",x);
   return buffer;
}
static int  createshmhelper(key_t k,int size,int flag)//static修饰只在本文件有效
{
  int shmid=shmget(k,size,flag);
  if(shmid==-1)//创建失败
  {
    cout<<errno<< " :" <<strerror(errno)<<endl;
       exit(2);
  }
  return  shmid;//返回共享内存标识符
}
int createshm(key_t k,int size)//创建共享内存
{
    //带有两个选项 若不存在则创建,若存在则报错
    return createshmhelper(k,size,IPC_CREAT |IPC_EXCL);
}
int getshm(key_t k,int size)
{
    //若有共享内存,则返回已有的共享内存
     return createshmhelper(k,size,IPC_CREAT );
}
char* attachshm(int shmid)//关联
{
    char*start=(char*)shmat(shmid,NULL,0);//对应类型void* 所以需要强转
     return start;
}
void detachshm(char*start)//取消关联
{
 int n=shmdt(start);
 assert(n!=-1);
 (void)n;
}
void delshm(int shmid)
{
   int n=shmctl(shmid,IPC_RMID,NULL);
   assert(n!=-1);//为-1就删除失败
   (void)n;
}
#endif 

server.cc

#include"comm.hpp"
#include<unistd.h>
int main()
{
    //1. 创建key值
  key_t k=getkey();//获取key值
  cout<<"server:"<<tohex(k)<<endl;
   //2.创建共享内存
   int shmid=createshm(k,gsize);//返回的是共享内存标识符
   cout<<"server shmid:"<<shmid<<endl;//将共享内存标识符转换为十六进制
   sleep(5);
   // 3.将自己和共享内存关联起来
   char*start=attachshm(shmid);
   //通信
   //4. 将自己和共享内存取消关联
    detachshm(start); 
   //5.删除共享内存
    delshm(shmid);
    return 0;
}

client.cc

#include"comm.hpp"
int main()
{
  key_t k=getkey();//获取key值
  cout<<"client key:"<<tohex(k)<<endl;
int shmid=getshm(k,gsize);//获取共享内存
cout<<"client shmid:"<<shmid<<endl;//将共享内存标识符转换为十六进制
  char*start=attachshm(shmid);
   detachshm(start); 
    return 0;
}

相关文章
|
1月前
|
监控 Linux
如何检查 Linux 内存使用量是否耗尽?这 5 个命令堪称绝了!
本文介绍了在Linux系统中检查内存使用情况的5个常用命令:`free`、`top`、`vmstat`、`pidstat` 和 `/proc/meminfo` 文件,帮助用户准确监控内存状态,确保系统稳定运行。
379 6
|
1月前
|
缓存 Java Linux
如何解决 Linux 系统中内存使用量耗尽的问题?
如何解决 Linux 系统中内存使用量耗尽的问题?
134 48
|
20天前
|
算法 Linux
深入探索Linux内核的内存管理机制
本文旨在为读者提供对Linux操作系统内核中内存管理机制的深入理解。通过探讨Linux内核如何高效地分配、回收和优化内存资源,我们揭示了这一复杂系统背后的原理及其对系统性能的影响。不同于常规的摘要,本文将直接进入主题,不包含背景信息或研究目的等标准部分,而是专注于技术细节和实际操作。
|
1月前
|
缓存 Ubuntu Linux
Linux环境下测试服务器的DDR5内存性能
通过使用 `memtester`和 `sysbench`等工具,可以有效地测试Linux环境下服务器的DDR5内存性能。这些工具不仅可以评估内存的读写速度,还可以检测内存中的潜在问题,帮助确保系统的稳定性和性能。通过合理配置和使用这些工具,系统管理员可以深入了解服务器内存的性能状况,为系统优化提供数据支持。
38 4
|
1月前
|
Linux
如何在 Linux 系统中查看进程占用的内存?
如何在 Linux 系统中查看进程占用的内存?
|
1月前
|
缓存 Linux
如何检查 Linux 内存使用量是否耗尽?
何检查 Linux 内存使用量是否耗尽?
|
1月前
|
算法 Linux 开发者
深入探究Linux内核中的内存管理机制
本文旨在对Linux操作系统的内存管理机制进行深入分析,探讨其如何通过高效的内存分配和回收策略来优化系统性能。文章将详细介绍Linux内核中内存管理的关键技术点,包括物理内存与虚拟内存的映射、页面置换算法、以及内存碎片的处理方法等。通过对这些技术点的解析,本文旨在为读者提供一个清晰的Linux内存管理框架,帮助理解其在现代计算环境中的重要性和应用。
|
28天前
|
存储 算法 安全
深入理解Linux内核的内存管理机制
本文旨在深入探讨Linux操作系统内核的内存管理机制,包括其设计理念、实现方式以及优化策略。通过详细分析Linux内核如何处理物理内存和虚拟内存,揭示了其在高效利用系统资源方面的卓越性能。文章还讨论了内存管理中的关键概念如分页、交换空间和内存映射等,并解释了这些机制如何协同工作以提供稳定可靠的内存服务。此外,本文也探讨了最新的Linux版本中引入的一些内存管理改进,以及它们对系统性能的影响。
|
1月前
|
存储 缓存 监控
|
1月前
|
缓存 算法 Linux
Linux内核中的内存管理机制深度剖析####
【10月更文挑战第28天】 本文深入探讨了Linux操作系统的心脏——内核,聚焦其内存管理机制的奥秘。不同于传统摘要的概述方式,本文将以一次虚拟的内存分配请求为引子,逐步揭开Linux如何高效、安全地管理着从微小嵌入式设备到庞大数据中心数以千计程序的内存需求。通过这段旅程,读者将直观感受到Linux内存管理的精妙设计与强大能力,以及它是如何在复杂多变的环境中保持系统稳定与性能优化的。 ####
41 0