iceoryx源码阅读(二)——共享内存管理

news/2024/10/1 12:21:38

目录
  • 1 共享内存模型
  • 2 获取共享内存
    • 2.1 MemoryManager::getChunk
    • 2.2 MemPool::getChunk
  • 3 释放共享内存
    • 3.1 SharedChunk::freeChunk
    • 3.2 MemPool::freeChunk
  • 4 总结

基于共享内存通信的核心在于共享内存的管理,包括共享内存的分配、释放。

1 共享内存模型

iceoryx先将整块共享内存粗略划分为多个MemPool,每个MemPool进一步划分为若干个相同大小的Chunk。每个MemPool中的Chunk数量及大小可以由用户配置,也可以使用默认配置。iceoryx中分配、回收共享内存的单位是Chunk,这种内存分配方式借鉴Linux内核中的Slab机制。共享内存的具体划分如下图所示:

image

其中,FreeIndices用于存放空闲Chunk索引的队列,以便于内存分配和释放。从上图中,共享内存管理的三级结构依次为MemoryManagerMemPoolChunk

2 获取共享内存

2.1 MemoryManager::getChunk

职责:
获取指定大小的Chunk(裸指针),并包装为SharedChunk

返回:
SharedChunk实例,类似智能指针,可以在适当的是好释放Chunk

expected<SharedChunk, MemoryManager::Error> MemoryManager::getChunk(const ChunkSettings& chunkSettings) noexcept
{void* chunk{nullptr};MemPool* memPoolPointer{nullptr};const auto requiredChunkSize = chunkSettings.requiredChunkSize();uint32_t aquiredChunkSize = 0U;for (auto& memPool : m_memPoolVector){uint32_t chunkSizeOfMemPool = memPool.getChunkSize();if (chunkSizeOfMemPool >= requiredChunkSize){chunk = memPool.getChunk();memPoolPointer = &memPool;aquiredChunkSize = chunkSizeOfMemPool;break;}}if (m_memPoolVector.size() == 0){IOX_LOG(FATAL) << "There are no mempools available!";errorHandler(iox::PoshError::MEPOO__MEMPOOL_GETCHUNK_CHUNK_WITHOUT_MEMPOOL, ErrorLevel::SEVERE);return err(Error::NO_MEMPOOLS_AVAILABLE);}else if (memPoolPointer == nullptr){IOX_LOG(FATAL) << "The following mempools are available:" << [this](auto& log) -> iox::log::LogStream& {this->printMemPoolVector(log);return log;} << "Could not find a fitting mempool for a chunk of size "<< requiredChunkSize;errorHandler(iox::PoshError::MEPOO__MEMPOOL_GETCHUNK_CHUNK_IS_TOO_LARGE, ErrorLevel::SEVERE);return err(Error::NO_MEMPOOL_FOR_REQUESTED_CHUNK_SIZE);}else if (chunk == nullptr){IOX_LOG(ERROR) << "MemoryManager: unable to acquire a chunk with a chunk-payload size of "<< chunkSettings.userPayloadSize()<< "The following mempools are available:" << [this](auto& log) -> iox::log::LogStream& {this->printMemPoolVector(log);return log;};errorHandler(iox::PoshError::MEPOO__MEMPOOL_GETCHUNK_POOL_IS_RUNNING_OUT_OF_CHUNKS, ErrorLevel::MODERATE);return err(Error::MEMPOOL_OUT_OF_CHUNKS);}else{auto chunkHeader = new (chunk) ChunkHeader(aquiredChunkSize, chunkSettings);auto chunkManagement = new (m_chunkManagementPool.front().getChunk())ChunkManagement(chunkHeader, memPoolPointer, &m_chunkManagementPool.front());return ok(SharedChunk(chunkManagement));}
}

逐段代码分析:

  • LINE 09 ~ LINE 19: 查找第一个Chunk大小超过应用所需大小的MemPool,并从中拿到空闲Chunk指针。
  • LINE 21 ~ LINE 50: 错误处理。
  • LINE 53 ~ LINE 56:

2.2 MemPool::getChunk

职责:
MemPool中获取未使用的Chunk

返回:
指向该Chunk的指针。

void* MemPool::getChunk() noexcept
{uint32_t l_index{0U};if (!m_freeIndices.pop(l_index)){IOX_LOG(WARN) << "Mempool [m_chunkSize = " << m_chunkSize << ", numberOfChunks = " << m_numberOfChunks<< ", used_chunks = " << m_usedChunks << " ] has no more space left";return nullptr;}/// @todo iox-#1714 verify that m_usedChunk is not changed during adjustMInFree///         without changing m_minFreem_usedChunks.fetch_add(1U, std::memory_order_relaxed);adjustMinFree();return m_rawMemory.get() + l_index * m_chunkSize;
}

整体代码分析

上述代码逻辑很简单,首先从m_freeIndices中弹出一个空闲Chunk的索引,正在使用的Chunk数量增1,根据索引计算并返回Chunk指针。

3 释放共享内存

3.1 SharedChunk::freeChunk

void SharedChunk::freeChunk() noexcept
{m_chunkManagement->m_mempool->freeChunk(static_cast<void*>(m_chunkManagement->m_chunkHeader.get()));m_chunkManagement->m_chunkManagementPool->freeChunk(m_chunkManagement);m_chunkManagement = nullptr;
}

3.2 MemPool::freeChunk

职责:
MemPool中获取未使用的Chunk

返回:
指向该Chunk的指针。

void MemPool::freeChunk(const void* chunk) noexcept
{cxx::Expects(m_rawMemory.get() <= chunk&& chunk <= m_rawMemory.get() + (static_cast<uint64_t>(m_chunkSize) * (m_numberOfChunks - 1U)));auto offset = static_cast<const uint8_t*>(chunk) - m_rawMemory.get();cxx::Expects(offset % m_chunkSize == 0);uint32_t index = static_cast<uint32_t>(offset / m_chunkSize);if (!m_freeIndices.push(index)){errorHandler(PoshError::POSH__MEMPOOL_POSSIBLE_DOUBLE_FREE);}m_usedChunks.fetch_sub(1U, std::memory_order_relaxed);
}

整体代码分析

根据相对首地址偏移和Chunk大小计算索引,将索引推入空闲索引队列m_freeIndices中,正在使用的Chunk数减1。

4 总结

本文学习了底层共享内存管理模型以及具体的分配和释放逻辑,上层的通信模块对共享内存Chunk的使用后续展开。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

iceoryx源码阅读(一)——全局概览

本系列文章对iceoryx源码进行解读。 一、什么是iceoryx iceoryx是一种基于共享内存实现的进程间通信组件,实现零拷贝传输。二、源码结构 iceoryx源码包括若干工程,整理如下表所示:下图展示了主要项目之间的依赖(FROM:iceoryx(冰羚)-Architecture):三、iceoryx应用程序结…

PVE安装Windows 95报错 while initializing device IOS

安装Win95重启后报错信息如下图,重启一直报错 while initializing device IOS,查了下报错原因说是 CPU频率太高导致,需要安装AMDK6UPD.EXE补丁包 下载地址 https://zhangka.lanzouw.com/igW0S1y8p5pe 打补丁操作流程: 1)将下载的iso文件加载到新光盘中 2)重启到dos环境…

第147天:免杀对抗-C2远控篇CC++ShellCode定性分析生成提取Loader加载模式编译执行

https://blog.csdn.net/qq_29948489/article/details/136180966 #C2远控-ShellCode-认知&环境 1.创建工程时关闭SDL检查 2.属性->C/C++->代码生成->运行库->多线程 (/MT)如果是debug则设置成MTD 3.属性->C/C++->代码生成->禁用安全检查GS 4.关闭生成清…

再探URLDNS链(手搓exp)

夜深了,想着还需要沉淀自己的基础能力,于是乎没有继续往CC链里爬,通过研究了一下ysoserial里的URLDNS链,决定自己尝试写一个类似却有些不同的exp,使自己的基础更加牢固一些,故有了今天这篇文章。 ysoserial里的URLDNS链我就不再多说,有兴趣的话自己可以去看下面这篇文章…

长安车机安装三方APP

前言 长安车机目前为基于安卓自研的系统。 目前 默认这个车机系统,不允许安装三方软件,具体表现为:插入u盘识别不出里边的apk文件。 自带的软件版本都特别低,且不支持升级,只能等待整个车机系统连带升级。 重点是,他们通常好几年不推送升级车机系统! 重点来了:没有攻破…

项目冲刺day2

这个作业属于哪个课程 软工4班这个作业要求在哪里 作业要求1.会议1. 照片2. 昨日已完成: 部分完成登录、注册功能。3.今天计划完成的工作 完成登录、注册功能,部分完成用户中心功能4.工作中遇到的困难 对框架不熟悉,出现很多报错。2.燃尽图3.每人的代码签入记录4.适当的项目…

musl-libc 安装与调试

musl-libc 官网:http://musl.libc.org1、下载与安装下载源码并解压编译参数./configure [option]... [VAR=VALUE]... option 说明 --help帮助 --prefix=DIR指定安装目录。默认为/usr/local/musl --host=HOST设置目标程序运行的CPU平台 一般不需要设置,除非你想要交叉编译 默…

El-table组件实现懒加载

背景 有的时候我们表格的数据不想使用分页组件展示,想要显示所有的数据,但是显示所有数据会导致服务器负荷严重(比如CPU过载),我们可以使用懒加载的形式,此方式利用监听是否滚动到元素底部,如果到元素底部就去请求下一页的数据 原理效果图示例代码 <template><di…