Tiniux 3.0 / Memory.c / OSMemInit

本文详细解析了Tiniux3.0操作系统中的内存管理机制,重点介绍了OSMemInit函数的工作原理,包括堆初始化、内存块记录结构tOSMem_t的使用,以及系统内存分布情况。通过本文,读者可以深入理解Tiniux如何管理和分配内存。
---------------------------------------------
-- 时间:2018-11-04
-- 创建人:Ruo_Xiao
-- 邮箱:xclsoftware@163.com
---------------------------------------------

一、前言

1、本博文是我自己的理解,在没有把握的地方我会特别注明。本人菜鸟一枚,真诚地期待大神地指教!

2、Tiniux 3.0下载地址

3、建议使用Source Inlight看源码,效率更高!

4、为了避免篇幅过长,博文源码中使用的一些数据类型就不多解释了,本文只针对终点区域做详解。

5、根据Memory.h头文件可知,函数一共5个,如下:

uOSBase_t  OSMemInit(void);
void *OSMemMalloc(uOSMemSize_t size);
void *OSMemCalloc(uOSMemSize_t count, uOSMemSize_t size);

void *OSMemTrim(void *pMem, uOSMemSize_t size);
void  OSMemFree(void *pMem);

二、OSMemInit

1、源码

/***************************************************************************** 
Function    : OSMemInit 
Description : Zero the heap and initialize start, end and lowest-free pointer.
Input       : None
Output      : None 
Return      : None 
*****************************************************************************/
uOSBase_t OSMemInit(void)
{
    tOSMem_t *ptOSMemTemp = OS_NULL;

    // align the heap 
    gpOSMemBegin = (uOS8_t *)OSMEM_ALIGN_ADDR(OSRAM_HEAP_POINTER);

    /* Initialize the stack tiniux used. */
    memset(gpOSMemBegin, 0U, OSMEM_SIZE_ALIGNED);

    // initialize the start of the heap 
    ptOSMemTemp = (tOSMem_t *)(void *)gpOSMemBegin;
    ptOSMemTemp->NextMem = OSMEM_SIZE_ALIGNED;
    ptOSMemTemp->PrevMem = 0;
    ptOSMemTemp->Used = 0;
    
    // initialize the end of the heap 
    gpOSMemEnd = (tOSMem_t *)(void *)&gpOSMemBegin[OSMEM_SIZE_ALIGNED];
    gpOSMemEnd->Used = 1;
    gpOSMemEnd->NextMem = OSMEM_SIZE_ALIGNED;
    gpOSMemEnd->PrevMem = OSMEM_SIZE_ALIGNED;

    // initialize the lowest-free pointer to the start of the heap 
    gpOSMemLFree = (tOSMem_t *)(void *)gpOSMemBegin;
    
    return 0U;
}

2、该函数的目的:

(1)将申请的堆初始化为0;

(2)设置指向堆开始位置的tOSMem_t结构体;

(3)设置指向堆结束位置和指向最低位置的已经释放内存的首地址的tOSMem_t结构体。

3、系统内存分布

gpOSMemEnd - gpOSMemBegin OSMEM_SIZE_ALIGNED

4、tOSMem_t

typedef struct _tOSMem 
{
  uOSMemSize_t NextMem;   
  uOSMemSize_t PrevMem;    
  uOS8_t Used;     
}tOSMem_t;

(1)作用:用于记录堆中已分配的和未分配的内存块在系统内存中的位置(首地址)。

(2)NextMem:中,下一个tOSMem_t的首地址。

(3)PrevMem:中,上一个tOSMem_t的首地址。

(4)Used:指明其后面的内存块是否被分配,0则为分配,非0则已分配。

(5)注意:tOSMem_t中的元素指明的地址是中的地址,gpOSMemBegingpOSMemEnd 和 gpOSMemLFree首地址都是系统内存中的地址。

5、在系统内存中申请堆

gpOSMemBegin = (uOS8_t *)OSMEM_ALIGN_ADDR(OSRAM_HEAP_POINTER);

(1)OSMEM_ALIGN_ADDR,地址对齐操作。

(2)OSRAM_HEAP_POINTER,堆数组的首地址。

#define OSMEM_SIZE_ALIGNED        OSMEM_ALIGN_SIZE(512)
uOS8_t OSRamHeap[OSMEM_SIZE_ALIGNED + (2U*SIZEOF_OSMEM_ALIGNED) + OSMEM_ALIGNMENT];
#define OSRAM_HEAP_POINTER OSRamHeap

A、上述代码的作用是申请512个字节的堆,但是为了在堆中包含两个tOSMem_t(gpOSMemEnd 和 gpOSMemLFree)同时为了数据对齐,则加上了(2U*SIZEOF_OSMEM_ALIGNED) + OSMEM_ALIGNMENT

B、特别声明:该数组类型为unsigned char,故1个字节即为1个元素,两个tOSMem_t首地址之间的差值就是二者在gpOSMemBegin数组中位置之间的差值。

6、对于刚刚分配好的堆,实际上就2个内存块,一个是ptOSMemTemp信息块和其对应的内存块,另一个是gpOSMemEnd信息块,如下图所示:

1、由于就两个内存块,故:ptOSMemTemp -> NextMem  = OSMEM_SIZE_ALIGNED

由于ptOSMemTemp之前没有节点,故:ptOSMemTemp -> PrevMem  = 0

同时由于该内存块没有分配,故:ptOSMemTemp -> Used = 0

2、由于gpOSMemEnd的作用是作为堆的尾端,故: gpOSMemEnd -> Used = 1。

同时为了不让其参加运算,孤立它,故:   

gpOSMemEnd -> NextMem = OSMEM_SIZE_ALIGNED;
gpOSMemEnd -> PrevMem = OSMEM_SIZE_ALIGNED;

 

三、拓展

解决了delete []ptr,在delete不知道该ptr数组大小的时候就准确地释放了内存的问题。原因就是在每一个已分配的内存块的前面都添加了相应的信息块,用于存放该存储块首尾在系统内存中的位置,如Tiniux中的tOSMem_t

 

 

(SAW:Game Over!)

 

 

`/dev/memcg/memory.avail_buffers` 是 Linux 内存控制组(memcg,即 Cgroup v1 的内存子系统)中的一个文件,用于查询或设置内存控制组中可用的 **缓冲内存(buffers)** 限制。以下是详细解释: --- ### **1. 文件作用** - **功能**: 该文件属于 Cgroup 内存子系统(`memory.cgroup`),用于记录或控制当前控制组中 **未被使用的缓冲内存(buffers)** 的可用量。 - **缓冲内存(buffers)**:Linux 内核用于临时存储块设备(如磁盘)I/O 操作的内存,通常通过 `buffer_head` 结构管理。 - **用途**: - 监控:读取该文件可获取当前控制组剩余的缓冲内存容量。 - 限制:写入值可设置该控制组允许使用的缓冲内存上限(需内核支持,部分版本可能只读)。 --- ### **2. 文件路径与上下文** - **路径**:`/dev/memcg/memory.avail_buffers` - 需挂载 Cgroup 内存子系统后访问(通常路径为 `/sys/fs/cgroup/memory/<group>/memory.avail_buffers`)。 - `/dev/memcg/` 可能是用户自定义的挂载点或符号链接。 - **相关文件**: - `memory.usage_in_bytes`:当前控制组已用内存(含缓存和缓冲)。 - `memory.limit_in_bytes`:控制组内存硬限制。 - `memory.stat`:详细内存统计(包括 `buffers` 字段)。 --- ### **3. 典型使用场景** #### **(1) 监控缓冲内存** ```bash cat /sys/fs/cgroup/memory/my_group/memory.avail_buffers ``` 输出示例: ``` 1024000 # 表示剩余 1000KB 可用缓冲内存 ``` #### **(2) 限制缓冲内存(若支持写入)** ```bash echo 512000 > /sys/fs/cgroup/memory/my_group/memory.avail_buffers ``` (注意:并非所有内核版本支持写入,通常需通过 `memory.limit_in_bytes` 间接控制。) --- ### **4. 注意事项** - **Cgroup 版本**: - Cgroup v1:明确支持 `memory.avail_buffers`。 - Cgroup v2:统一内存统计在 `memory.current` 中,无单独 `buffers` 文件,需通过 `memory.stat` 解析。 - **内核配置**: 需启用 `CONFIG_MEMCG` 和 `CONFIG_MEMCG_KMEM`(若需跟踪内核内存)。 - **缓冲内存 vs 缓存(cache)**: - 缓冲(buffers):块设备 I/O 中间数据。 - 缓存(cache):文件系统缓存(通过 `memory.avail_cache` 类似文件控制,若存在)。 --- ### **5. 示例代码(读取值)** ```c #include <stdio.h> int main() { FILE *file = fopen("/sys/fs/cgroup/memory/my_group/memory.avail_buffers", "r"); if (file) { long avail_buffers; fscanf(file, "%ld", &avail_buffers); printf("Available buffers: %ld bytes\n", avail_buffers); fclose(file); } return 0; } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值