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 ...
随机推荐
- Loadrunner之脚本的调试和保存(六)
一.调试脚本 脚本录制完毕后,按F5键或单击菜单上的RUN按钮,可以运行脚本. 在VIRTUAL USER GENERATOR中运行脚本的作用,主要是查看录制的脚本能否正常通过,如果有问题 ...
- 【转载】GDI 映像方式 之 SetViewportOrgEx 与 SetWindowOrgEx 解析
SetViewportOrgEx 与 SetWindowOrgEx 解析 这两个函数,用来改变视端口和窗口的原点,并都具有改变轴的效果,以致(0,0)不再指左上角. 「视端口」是依据设备坐标(图素)的 ...
- angularJS Directive学习
Directive 指令 直接上实例 index.html <!doctype html> <html ng-app="drag"> <head> ...
- Sea.Js的运行原理(转)
1.CMD(Common Module Definition)规范 Sea.js采用了和Node相似的CMD规范,使用require.exports和module来组织模块.但Sea.js比起Node ...
- BootStrap详解之(一)
一.BootStrap简介 BootStrap是一个用来构建网站前段框架的一个插件.无论你是想构建应用程序.博客还是CMS网站,Bootstrap都特别的使用,只要你想得到,它就能行.Bootstra ...
- js数据显示在文本框中(页面加载显示和按钮触动显示)
web代码如下: <!DOCTYPE html> <html> <head> <title>jsTest02.html</title> &l ...
- OpenGL学习--------颜色的选择
OpenGL支持两种颜色模式:一种是RGBA,一种是颜色索引模式.无论哪种颜色模式,计算机都必须为每一个像素保存一些数据.不同的是,RGBA模式中,数据直接就代表了颜色:而颜色索引模式中,数据代表的是 ...
- CALayer --> UIView
一.CALayer和UIView的关系 UIView显示在屏幕上归功于CALayer 可以说:UIView依赖CALayer,又高于CALayer 通过调用drawRect方法来渲染自身的内容,调节C ...
- wind10系统 Atheros AR9271 Wireless Network Adapter USBwifi无线网卡的驱动安装解决无法搜索wifi信号,连接wifi信号无法上网的问题
一.解决无法搜索wifi信号的问题 卸载掉之前的驱动,上网下载其他的驱动程序安装. http://drivers.mydrivers.com/drivers/463_185289.htm 二.安装完后 ...
- JAVA基础-- 对象转型 (casting)
1. 一个基类的引用类型变量可以指向其子类的对象: a=new Dog("bigyellow","yellow"); 2. 一个基类的引用不可以访问其子类对象新 ...