【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;
}

相关文章
|
3月前
|
缓存 监控 Linux
Linux内存问题排查命令详解
Linux服务器卡顿?可能是内存问题。掌握free、vmstat、sar三大命令,快速排查内存使用情况。free查看实时内存,vmstat诊断系统整体性能瓶颈,sar实现长期监控,三者结合,高效定位并解决内存问题。
276 0
Linux内存问题排查命令详解
|
11月前
|
缓存 Linux
linux 手动释放内存
在 Linux 系统中,内存管理通常自动处理,但业务繁忙时缓存占用过多可能导致内存不足,影响性能。此时可在业务闲时手动释放内存。
514 17
|
7月前
|
缓存 Linux 数据安全/隐私保护
Linux环境下如何通过手动调用drop_caches命令释放内存
总的来说,记录住“drop_caches” 命令并理解其含义,可以让你在日常使用Linux的过程中更加娴熟和自如。
1216 23
|
9月前
|
监控 Linux Python
Linux系统资源管理:多角度查看内存使用情况。
要知道,透过内存管理的窗口,我们可以洞察到Linux系统运行的真实身姿,如同解剖学家透过微观镜,洞察生命的奥秘。记住,不要惧怕那些高深的命令和参数,他们只是你掌握系统"魔法棒"的钥匙,熟练掌握后,你就可以骄傲地说:Linux,我来了!
296 27
|
10月前
|
消息中间件 Linux
Linux中的System V通信标准--共享内存、消息队列以及信号量
希望本文能帮助您更好地理解和应用System V IPC机制,构建高效的Linux应用程序。
392 48
|
10月前
|
缓存 NoSQL Linux
Linux系统内存使用优化技巧
交换空间(Swap)的优化 禁用 Swap sudo swapoff -a 作用:这个命令会禁用系统中所有的 Swap 空间。swapoff 命令用于关闭 Swap 空间,-a 参数表示关闭 /etc/fstab 文件中配置的所有 Swap 空间。 使用场景:在高性能应用场景下,比如数据库服务器或高性能计算服务器,禁用 Swap 可以减少磁盘 I/O,提高系统性能。
388 3
|
10月前
|
缓存 Linux
Linux查看内存命令
1. free free命令是最常用的查看内存使用情况的命令。它显示系统的总内存、已使用内存、空闲内存和交换内存的总量。 free -h • -h 选项:以易读的格式(如GB、MB)显示内存大小。 输出示例: total used free shared buff/cache available Mem: 15Gi 4.7Gi 4.1Gi 288Mi 6.6Gi 9.9Gi Swap: 2.0Gi 0B 2.0Gi • to
756 2
|
11月前
|
消息中间件 Linux
Linux:进程间通信(共享内存详细讲解以及小项目使用和相关指令、消息队列、信号量)
通过上述讲解和代码示例,您可以理解和实现Linux系统中的进程间通信机制,包括共享内存、消息队列和信号量。这些机制在实际开发中非常重要,能够提高系统的并发处理能力和数据通信效率。希望本文能为您的学习和开发提供实用的指导和帮助。
794 20
|
12月前
|
Linux
【Linux】System V信号量详解以及semget()、semctl()和semop()函数讲解
System V信号量的概念及其在Linux中的使用,包括 `semget()`、`semctl()`和 `semop()`函数的具体使用方法。通过实际代码示例,演示了如何创建、初始化和使用信号量进行进程间同步。掌握这些知识,可以有效解决多进程编程中的同步问题,提高程序的可靠性和稳定性。
602 19
|
5月前
|
存储
阿里云轻量应用服务器收费标准价格表:200Mbps带宽、CPU内存及存储配置详解
阿里云香港轻量应用服务器,200Mbps带宽,免备案,支持多IP及国际线路,月租25元起,年付享8.5折优惠,适用于网站、应用等多种场景。
1706 0