-
Notifications
You must be signed in to change notification settings - Fork 1
文档:内存管理
Contiki-NG支持静态和动态内存分配。 在嵌入式系统中,传统上,内存分配仅限于静态大小,因为静态内存没有泄漏和碎片。 但是,当运行时内存需求发生变化时,静态内存将很麻烦。 此类更改可能发生在跟踪连接的Web服务器或支持动态编程语言的虚拟机中。 当限制为静态内存时,程序员必须猜测资源的最大使用量,并过度分配内存块以防止内存耗尽。 为了缓解此类问题,我们在静态内存之外还提供了两种不同类型的内存分配器:半动态MEMB模块和动态HeapMem模块。
在os/lib/memb.h
中声明的MEMB
库提供了一组内存块管理功能。 内存块被分配为大小恒定的对象数组,并放置在静态内存中。 API如下所示:
Function | Purpose |
---|---|
MEMB(name, structure, num) |
声明一个内存块 |
void memb_init(struct memb *m) |
初始化一个内存块 |
void *memb_alloc(struct memb *m) |
分配一个内存块 |
char memb_free(struct memb *m, void *ptr) |
释放一个内存块 |
int memb_inmemb(struct memb *m, void *ptr) |
检查一个地址是否是内存块 |
MEMB()
宏声明一个内存块,其类型为 struct memb
。 由于该块已放入静态内存中,因此通常将其放置在使用内存块的C源文件的顶部。 name
标识存储块,以后用作其他存储块功能的参数。 structure
参数指定内存块的类型,num
表示内存块可容纳的对象数量。 struct memb
的定义如下:
struct memb {
unsigned short size;
unsigned short num;
char *count;
void *mem;
};
MEMB
宏的扩展产生了三个定义静态内存的语句。 一个语句存储该内存块可以容纳的对象数量。 由于数量存储在unsigned short
类型的变量中,因此存储块最多可以容纳USHRT_MAX
个对象。 第二条语句分配由structure
参数引用的类型为num
的结构数组。
一旦使用MEMB()
声明了内存块,就必须通过调用memb_init()
对其进行初始化。 此函数采用struct memb
的参数来标识内存块。
初始化struct memb
之后,我们准备开始使用memb_alloc()
从中分配对象。 通过相同的struct memb
分配的所有对象都具有相同的大小,这由MEMB()
的structure
参数的大小确定。 如果操作成功,则memb_alloc()
返回指向已分配对象的指针;如果内存块中没有空闲对象,则返回NULL。
memb_free()
释放以前使用memb_alloc()
分配的对象。 需要两个参数来释放对象:m
指向内存块,而ptr
指向内存块中的对象。
可以检查任何指针以确定其是否在存储块的数据区域内。 如果ptr
在内存块m
内,则memb_inmemb()
返回1;如果指向未知内存,则返回0。
我们展示了如何使用MEMB
模块的示例。open_connection()
函数为套接字标识的每个新连接分配一个新的结构连接变量。 关闭连接后,我们将释放内存块用于struct
连接变量。
#include "contiki.h"
#include "lib/memb.h"
struct connection {
int socket;
};
MEMB(connections, struct connection, 16);
struct connection *
open_connection(int socket)
{
struct connection *conn;
conn = memb_alloc(&connections);
if(conn == NULL) {
return NULL;
}
conn->socket = socket;
return conn;
}
void
close_connection(struct connection *conn)
{
memb_free(&connections, conn);
}
标准C库提供了一组用于分配和释放堆内存空间中的内存的函数。 对于不同的编译器工具链,目前尚不清楚默认堆内存模块在资源受限的执行环境中的性能如何。 在某些malloc
实现中,大小不同的对象上的分配和释放模式可能更成问题。 因此,Contiki-NG包括一个堆内存模块,该模块已在各种硬件平台和不同的应用程序上使用。 HeapMem
模块的API与标准C相似。为避免名称冲突,HeapMem中的函数名称为heapmem_alloc()
、heapmem_realloc()
和heapmem_free()
而不是malloc()
、realloc()
和free()
。 该API如下表所示:
Function | Purpose |
---|---|
void *heapmem_alloc(size_t size) |
分配未初始化的内存 |
void *heapmem_realloc(void *ptr, size_t size) |
重新分配内存块的大小 |
void heapmem_free(void *ptr) |
释放内存 |
本节中列出的所有函数都在C头文件os/lib/heapmem.h
中声明。 heapmem_alloc()
函数在堆上分配大小的内存字节。 如果成功分配了内存,heapmem_alloc()
将返回一个指向它的指针。 如果没有足够的连续可用内存,heapmem_alloc()
将返回NULL。
heamem_realloc()
函数以新的大小重新分配先前分配的块ptr
。 如果新块较小,则将旧块中数据的大小字节复制到新块中。 如果新块较大,则将复制完整的旧块,而新块的其余部分将包含未指定的数据。 一旦分配了新块并填充了其内容,便会释放旧块。 如果无法分配该块,heapmem_realloc()
将返回NULL。 如果重新分配成功,heapmem_realloc()
将返回一个指向新块的指针。
heapmem_free()
会释放先前通过heapmem_alloc()
或heapmem_realloc()
分配的块。 参数ptr
必须指向已分配块的开始。