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

相关文章
|
15天前
|
存储 Linux Android开发
Volatility3内存取证工具安装及入门在Linux下的安装教程
Volatility 是一个完全开源的工具,用于从内存 (RAM) 样本中提取数字工件。支持Windows,Linux,MaC,Android等多类型操作系统系统的内存取证。针对竞赛这块(CTF、技能大赛等)基本上都是用在Misc方向的取证题上面,很多没有听说过或者不会用这款工具的同学在打比赛的时候就很难受。以前很多赛项都是使用vol2.6都可以完成,但是由于操作系统更新,部分系统2.6已经不支持了,如:Win10 等镜像,而Volatility3是支持这些新版本操作系统的。
|
8天前
|
监控 Linux 数据处理
探索Linux中的`lsmem`命令:深入了解系统内存布局
`lsmem`是Linux命令,用于显示系统内存布局和大小,帮助管理员和开发者理解内存使用情况。它提供详细输出,包括内存块的大小、范围、类型和关联,支持多种格式展示,如树状图。命令参数如`-h`显示帮助,`-t`以树形展示,`--human-readable`使大小更易读。需root权限运行,常与`free`、`vmstat`等工具结合使用,用于监控和优化内存。注意不同发行版可能存在兼容性差异。
|
7天前
|
存储 缓存 算法
【原创】(十)Linux内存管理 - zoned page frame allocator - 5(1)
【原创】(十)Linux内存管理 - zoned page frame allocator - 5
|
9天前
|
Java Linux PHP
【应急响应】后门攻击检测指南&Rookit&内存马&权限维持&WIN&Linux
【应急响应】后门攻击检测指南&Rookit&内存马&权限维持&WIN&Linux
|
1天前
|
监控 Linux
深入了解Linux的pmap命令:进程内存映射的利器
`pmap`是Linux下分析进程内存映射的工具,显示内存区域、权限、大小等信息。通过`/proc/[pid]/maps`获取数据,特点包括详细、实时和灵活。参数如`-x`显示扩展信息,`-d`显示设备。示例:`pmap -x 1234`查看进程1234的映射。注意权限、实时性和准确性。结合其他工具定期监控,排查内存问题。
|
2天前
|
存储 机器学习/深度学习 Linux
程序员必知:关于Linux内存寻址与页表处理的一些细节
程序员必知:关于Linux内存寻址与页表处理的一些细节
|
2天前
|
Linux
【linux】共享内存
【linux】共享内存
6 0
|
3天前
|
Linux 芯片
一篇文章讲明白Linux内核态和用户态共享内存方式通信
一篇文章讲明白Linux内核态和用户态共享内存方式通信
|
7天前
|
存储 缓存 Linux
【原创】(十)Linux内存管理 - zoned page frame allocator - 5(2)
【原创】(十)Linux内存管理 - zoned page frame allocator - 5
|
9天前
|
存储 安全 Unix
【内网安全】Win&Linux&内存离线读取&Hashcat破解&RDP&SSH存储提取
【内网安全】Win&Linux&内存离线读取&Hashcat破解&RDP&SSH存储提取