ucos内存管理原理详解
应用程序中为了某种特殊需要,经常需要动态的分配内存,而操作系统的特质置一,就是能不能保证动态内存分配的时效性,也就是说分配时间是可确定的
Ucos提供内存分配功能,它将内存空间分为两级管理,将一块连续的内存空间分为若干个分区,每个分区单位又分成大小相同的若干个内存块,分区时操作系统的管理单位,而内存块是分配单位,内存分区以及内存块的使用情况有一个叫做内存控制块的表来记录,内存控制块的基本结构如下
typedef struct os_mem {
void *OSMemAddr;
void *OSMemFreeList;
INT32U OSMemBlkSize;
INT32U OSMemNBlks;
INT32U OSMemNFree;
#if OS_MEM_NAME_EN > 0u
INT8U *OSMemName;
#endif
} OS_MEM;
OSMemAddr 内存分区的指针
OSMemFreeList 内存控制块链表的指针
OSMemBlkSize 内存块的长度
OSMemNBlks 分区内内存块的数目
OSMemNFree 分区内部当前可分配内存块数目
系统在初始化的时候将当前系统内部的所有内存控制块构成一个链表,叫做空闲内存控制块表,变量如下
OS_EXT OS_MEM *OSMemFreeList;
而系统初始时刻存在的内存控制块的数目是给定的
OS_EXT OS_MEM OSMemTbl[OS_MAX_MEM_PART];
OS_MAX_MEM_PART是一个宏,决定系统拥有几个内存分区,在os_cfg.h文件中定义
初始化内存控制块列表的函数为OS_MemInit,其中的核心code为
OS_MemClr((INT8U *)&OSMemTbl[0], sizeof(OSMemTbl));
for (i = 0u; i < (OS_MAX_MEM_PART - 1u); i++) {
pmem = &OSMemTbl[i];
pmem->OSMemFreeList = (void *)&OSMemTbl[i + 1u];
#if OS_MEM_NAME_EN > 0u
pmem->OSMemName = (INT8U *)(void *)"?";
#endif
}
pmem = &OSMemTbl[i];
pmem->OSMemFreeList = (void *)0;
#if OS_MEM_NAME_EN > 0u
pmem->OSMemName = (INT8U *)(void *)"?";
#endif
OSMemFreeList = &OSMemTbl[0];
类似于tcb初始化的流程,也是将一个数组链表化,并且将OSMemFreeList指向链表的开头,此时系统是还没有开始管理内存的,因为我们并没有告诉系统我们可分配的内存在哪里,那在哪儿指明了呢,答案是在OSMemCreate中,该函数初始化一个内存分区,并返回一个内存分区控制结构体,函数原型如下
OS_MEM *OSMemCreate (void *addr,INT32U nblks,INT32U blksize,INT8U *perr)
指明我们空闲内存分区的开始地址,我们分配的内存块的长度以及内存块的数目,三者计算就能得到我们分配的内存大小nblks*blksize
在OSMemCreate中先做了以下操作
plink = (void **)addr;
pblk = (INT8U *)addr;
loops = nblks - 1u;
for (i = 0u; i < loops; i++) {
pblk += blksize;
*plink = (void *)pblk;
plink = (void **)pblk;
}
这句话实现的实际上是将一个内存分区分解为nblks个内存块,然后在每一个内存块的最头上位置放置了一个指针,这个指正指向下一个内存块的首地址,用图比较好解释

如上就是基本的内存管理结构了
pmem->OSMemAddr = addr;
pmem->OSMemFreeList = addr;
pmem->OSMemNFree = nblks;
pmem->OSMemNBlks = nblks;
pmem->OSMemBlkSize = blksize;
接下来就是进行了内存控制块的赋值操作,也就是说,ucos的两级内存管理实际上是通过两级链表来操作的.空闲内存控制块构成一个空闲链表,分配的内存块有内存块本身包含的指针形成单向链表,此时内存控制块的指向为可分配内存的头
而向操作系统申请内存块的函数为OSMemGet,其核心流程代码如下
if (pmem->OSMemNFree > 0u) {
pblk = pmem->OSMemFreeList;
pmem->OSMemFreeList = *(void **)pblk;
pmem->OSMemNFree--;
该函数需要我们给出一个内存控制块指针,函数从控制块中返回空闲内存,首先检测控制块内是否还有空闲内存,若有,将最近的空闲内存返回,控制快内空闲内存-1, OSMemFreeList指向下一个空闲内存块的首地址.
而释放内存块的操作使用OSMemPut完成,该函数接受两个参数,一个是空闲内存控制块的指针,一个是想要释放的内存指针,核心代码为
*(void **)pblk = pmem->OSMemFreeList;
pmem->OSMemFreeList = pblk;
pmem->OSMemNFree++;
通过分析以上代码可以得出,新释放的内存块被插入到空闲块的最头上地址,控制块中的空闲块指针指向释放的地址,释放地址的首地址存放原来的第一个空闲块的地址,链表恢复,并将空闲内存++;
另外可以通过OSMemQuery查询内存分区的状态,简单接口,不再赘述
但是一定要注意,ucos的内存管理是存在问题的!
在OSMemCreate中有以下语句
INT8U *pblk;
这是一个八位指针,后面在进行内存块划分的时候有以下代码
for (i = 0u; i < loops; i++) {
pblk += blksize;
但是pblk是8位的,最多只能支持255内存管理,32位内存空间的话就不能用这个,所以32位寻址的时候,需要修改这部分的东西,我推荐这个部分的内存管理代码可以自己写,反正和操作系统任务调度也没有关系
ucos内存管理原理详解的更多相关文章
- ARC内存管理机制详解
ARC在OC里面个人感觉又是一个高大上的牛词,在前面Objective-C中的内存管理部分提到了ARC内存管理机制,ARC是Automatic Reference Counting---自动引用计数. ...
- object-c(oc)内存管理机制详解
1.内存的创建和释放 让我们以Object-c世界中最最简单的申请内存方式展开,谈谈关于一个对象的生命周期.首先创建一个对象: 1 2 3 //“ClassName”是任何你想写的类名,比如NSStr ...
- iOS- 非ARC的项目内存管理细节详解(实战)
1.前言 接上文:iOS- 如何将非ARC的项目转换成ARC项目(实战) 2.内存管理时相关的配置 当我们把将非ARC的内存管理都管理好后,发现在做有些操作的时候内存还是在一直的缓慢增加 比如做一个最 ...
- Namenode HA原理详解(脑裂)
转自:http://blog.csdn.net/tantexian/article/details/40109331 Namenode HA原理详解 社区hadoop2.2.0 release版本开始 ...
- 转 Linux内存管理原理
Linux内存管理原理 在用户态,内核态逻辑地址专指下文说的线性偏移前的地址Linux内核虚拟3.伙伴算法和slab分配器 16个页面RAM因为最大连续内存大小为16个页面 页面最多16个页面,所以1 ...
- NFS原理详解
NFS原理详解 摘自:http://atong.blog.51cto.com/2393905/1343950 2013-12-23 12:17:31 标签:linux NFS nfs原理详解 nfs搭 ...
- 0614MySQL的InnoDB索引原理详解
转自http://www.cnblogs.com/shijingxiang/articles/4743324.html MySQL的InnoDB索引原理详解 http://www.admin10000 ...
- CentOS 6.5 iptables原理详解以及功能说明
CentOS 6.5 iptables原理详解以及功能说明 来源 https://blog.51cto.com/tanxw/1389114 前言 iptables其实就是Linux下的一个开源的信息过 ...
- 【转贴】内存重要参数详解 RAS CAS
内存重要参数详解 RAS CAS 分类: LINUX 2014-09-12 09:41:58 原文地址:内存重要参数详解 RAS CAS 作者:Reny http://blog.chinaunix.n ...
随机推荐
- mysql 修改 添加 删除 表字段
添加表的字段 alter table 表名 add 字段名 字段的类型 例子: alter table table1 add transactor varchar(10) n ...
- C#,js数据排序及其操作
List<int> listint=new List<int>{2,1,7,3,8,5,4,6};listint.Sort((x, y) => x - y); var a ...
- elasticsearch高级配置之(一)----分片分布规则设置
cluster.routing.allocation.allow_rebalance 设置根据集群中机器的状态来重新分配分片,可以设置为always, indices_primaries_active ...
- [原]点击按钮,表格隔行变色:偶数行为黄色背景,奇数行为默认颜色。通过table的getElementsByTagName取得所有的tr,依次遍历,如果是偶数就…………。
window.onload = function () { document.getElementById('btn').onclick = function () { ...
- Ubuntu VPN PPTP 连接要选上这个啊
选上MPPE点到点加密..
- 【使用Itext处理PDF文档(新建PDF文件、修改PDF文件、PDF中插入图片、将PDF文件转换为图片)】
iText简介 iText是著名的开放源码的站点sourceforge一个项目,是用于生成PDF文档的一个java类库.通过iText不仅可以生成PDF或rtf的文档,而且可以将XML.Html文件转 ...
- 帝国CMS系统结合项图文教程
为了使信息列表可实现按多种条件输出数据,帝国CMS独创可设置无限条件的模型结合项功能.帝国CMS的结合项功能是指按模型多个字段内容来结合显示对应的信息. 二.结合项的语法说明 结合项访问地址: /e/ ...
- cc2530串口通信流程
//串口发送接收流程 main: //主函数 ->osal_init_system(); //操作系统初始化 ->osalInitTasks(); //任务初始化 -->ZDApp_ ...
- Android学习笔记之ContentProvider
读取其他应用程序共享的数据 以下示例为读取联系人信息 package com.jiahemeikang.helloandroid; import com.jiahemikang.service.Ech ...
- CodeForces 614D Skills
排序+枚举+二分 最大的那些变成A,小的那部分提高最小值 #include<cstdio> #include<cstring> #include<cmath> #i ...