contiki源码阅读之mmem.c
上次我们说了list,这次我们就借着mmem.c的代码来用一下这个链表。
代码目录是./core/lib/mmem.c
结构体定义如下
struct mmem {
struct mmem *next;
unsigned int size;
void *ptr;
};
请注意,第一个成员必须是指针,这样才可以借用list的代码。
第二个成员是要申请的字节数,第三个成员是指针,指向返回内存的首地址。
插句话,对于单片机,如果想内存管理(不考虑虚拟地址,只考虑物理地址),主要有两种方法。一种是引出堆的指针,在此基础上自己封装,把这个堆管理起来(没有尝试过这种方法,也没有读到这方面的资料,留待以后研究。)还有一种方法,就是简单的定义一片全局变量,把这些空间管理起来。今天讨论的是第二种方法。
#ifdef MMEM_CONF_SIZE
#define MMEM_SIZE MMEM_CONF_SIZE
#else
#define MMEM_SIZE 4096
#endif LIST(mmemlist);
unsigned int avail_memory;
static char memory[MMEM_SIZE];
这里定义了全局数组,4096个字节。
定义了全局变量avail_memory,用来记录还剩余多少个字节没有分配。
定义了一个链表(上次已经介绍过相关代码了)。
void
mmem_init(void)
{
list_init(mmemlist);
avail_memory = MMEM_SIZE;
}
初始化函数,初始化链表并且设置全局变量avail_memory=4096,4K个字节。
在上次的list.h文件中,可以看到作者这样的注释:
A linked list is made up of elements where the first element must be a pointer. This pointer is used by the linked list library to form lists of the elements.
这呼应了开头的话,因为list里面就是一个指针,所以用户的结构体必须把指针作为第一个成员,这样才能在不同指针(用户的结构体和 struct list)之间自由转换而不会发生错位。
int
mmem_alloc(struct mmem *m, unsigned int size)
{
/* Check if we have enough memory left for this allocation. */
if(avail_memory < size) {
return 0;
} /* We had enough memory so we add this memory block to the end of
the list of allocated memory blocks. */
list_add(mmemlist, m); /* Set up the pointer so that it points to the first available byte
in the memory block. */
m->ptr = &memory[MMEM_SIZE - avail_memory];//这句赋值,把那段全局数组和m里面的指针联系起来了,有了m,就能找到那片内存 /* Remember the size of this memory block. */
m->size = size; /* Decrease the amount of available memory. */
avail_memory -= size; /* Return non-zero to indicate that we were able to allocate
memory. */
return 1;
}
这就是内存分配函数。
void
mmem_free(struct mmem *m)
{
struct mmem *n; if(m->next != NULL) {
/* Compact the memory after the allocation that is to be removed
by moving it downwards. */
memmove(m->ptr, m->next->ptr,
&memory[MMEM_SIZE - avail_memory] - (char *)m->next->ptr); /* Update all the memory pointers that points to memory that is
after the allocation that is to be removed. */
for(n = m->next; n != NULL; n = n->next) {
n->ptr = (void *)((char *)n->ptr - m->size);
}
} avail_memory += m->size; /* Remove the memory block from the list. */
list_remove(mmemlist, m);
}
内存的释放。首先看看要释放的是不是链表的最后一个元素,如果是,那么就简单了,把字节数还回去,再把这块内存从链表上脱离。
如果不是,就要进行字节的拷贝。把这个内存之后的所有内容(内存的末尾减去后面的内存块的起始地址)向前面移动(移动的距离刚好是这个内存块的大小)。
但是这样还没有完,因为后面的内存块移动了,所以要修改每个内存块的指针,指针的值也要相应减少m->size个字节。
这样做的好处是什么,就是没有内存碎片。因为每次释放,都会把后面的内容移动到前面,填补释放的空洞。
contiki源码阅读之mmem.c的更多相关文章
- contiki源码阅读之list
我们阅读一下contiki的源码,list.c(路径是./core/lib/list.h). #include "lib/list.h" #define NULL 0 struct ...
- Contiki源码结构
Contiki源码结构 apps目录下,用于存放Application,也就是我们的应用程序放在这个目录下.如webserver,webrowser等,如下图所示. core目录是contiki操作系 ...
- 【原】FMDB源码阅读(三)
[原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...
- 【原】FMDB源码阅读(二)
[原]FMDB源码阅读(二) 本文转载请注明出处 -- polobymulberry-博客园 1. 前言 上一篇只是简单地过了一下FMDB一个简单例子的基本流程,并没有涉及到FMDB的所有方方面面,比 ...
- 【原】FMDB源码阅读(一)
[原]FMDB源码阅读(一) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 说实话,之前的SDWebImage和AFNetworking这两个组件我还是使用过的,但是对于 ...
- 【原】AFNetworking源码阅读(六)
[原]AFNetworking源码阅读(六) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 这一篇的想讲的,一个就是分析一下AFSecurityPolicy文件,看看AF ...
- 【原】AFNetworking源码阅读(五)
[原]AFNetworking源码阅读(五) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇中提及到了Multipart Request的构建方法- [AFHTTP ...
- 【原】AFNetworking源码阅读(四)
[原]AFNetworking源码阅读(四) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇还遗留了很多问题,包括AFURLSessionManagerTaskDe ...
- 【原】AFNetworking源码阅读(三)
[原]AFNetworking源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇的话,主要是讲了如何通过构建一个request来生成一个data tas ...
随机推荐
- 国内物联网平台(3):QQ物联智能硬件开放平台
国内物联网平台(3)——QQ物联·智能硬件开放平台 马智 平台定位 将QQ帐号体系.好友关系链.QQ消息通道及音视频服务等核心能力提供给可穿戴设备.智能家居.智能车载.传统硬件等领域的合作伙伴,实现用 ...
- 关于windows2012-远程复制粘贴无效的解决方法
1:在远程桌面中右键点击,选择启动任务管理器,杀掉进程 2:重启服务即可:
- 大众点评CAT开源监控系统剖析
参考文档: 大众点评的实时监控系统分析(一) CAT_source_analyze 透过CAT,来看分布式实时监控系统的设计与实现 深度剖析开源分布式监控CAT [分布式监控CAT] Client端源 ...
- 【图灵学院15】极致优化-高性能网络编程之BIO与NIO区别
一.Java IO概念 1. 一个http请求节点 数据传输 1)网络传输 TCP.UDP 2)通信模型 BIO.NIO.AIO 数据处理 3)应用协议 HTTP.RMI.WEBSERVICE.Re ...
- 用 LVS 搭建一个负载均衡集群(转)
http://blog.jobbole.com/87503/ 第一篇:<如何生成每秒百万级别的 HTTP 请求?> 第二篇:<为最佳性能调优 Nginx> 第三篇:<用 ...
- v$sqlarea,v$sql,v$sqltext这三个视图提供的sql语句有什么区别?
v$sqltext存储的是完整的SQL,SQL被分割 SQL> desc v$sqltextName Null? ...
- 【Python OpenGL】【2】第一个三角形(Pyopengl)
根据顶点缓存来生成图元(Python OpenGL) 原文(英文链接)http://ogldev.atspace.co.uk/www/tutorial03/tutorial03.html __auth ...
- P4172 [WC2006]水管局长 LCT维护最小生成树
\(\color{#0066ff}{ 题目描述 }\) SC 省 MY 市有着庞大的地下水管网络,嘟嘟是 MY 市的水管局长(就是管水管的啦),嘟嘟作为水管局长的工作就是:每天供水公司可能要将一定量的 ...
- 【三支火把】--- 关于BIOS&UEFI查阅资料网站总结
UEFI和BIOS的水太深,网上能找到的资料是那么的少,各个组织之间互有交叉,难弄的很,总结了下常用的BIOS资料网站,仅供参考,如果遗漏之处,请指出,博主将继续完善补充……
- C++_派生类的构造函数及派生类和基类之间的特殊关系
派生类和基类的概念及派生类构造函数的原理: 创建一个叫做TableTennisPlayer的基类,记录会员的名字和是否有球桌. //声明一个基类 class TableTennisPlayer { p ...