请在网上先了解:什么是内存管理?有什么作用?为它这么重要?再继续下文阅读。。。。
因为在OS里面,每一个组件都有它存在原因和价值,当你不了解这些时,会是一头雾水。
在contiki-ng-release-v4.6\os\lib内,有俩种内存管理是静态内存和动态内存。
就是memb.c; memb.h和heapmem.c; heapmem.h。
要了解和掌握它们,我们最好先学习C下的基本方法:
1 #include <stdio.h> 2 #include <stdlib.h>//利用malloc()进行动态内存分配 3 4 typedef struct{//定义一个结构体类刑,关于书的数据 5 char title[64]; 6 int price; 7 char isbn[32]; 8 }BookData; 9 10 BookData *bok_dat_p;//定义个指针 11 12 int main() 13 { 14 printf("test1:%p \n", bok_dat_p->title); //未分配时?? 15 16 bok_dat_p = malloc(sizeof(BookData));//为bok_dat_p分配内存区域 17 if(!bok_dat_p){ //检查是不是分配成功 18 printf("err:no RAM\n"); 19 return 0; 20 } 21 printf("test2:%p \n", bok_dat_p->title);//正常分配后?? 22 23 printf("bok_dat_p:%d \n", sizeof(bok_dat_p));//指针自己的大小 24 printf("bok_dat_p-max:%d \n", sizeof(*bok_dat_p));//指向内存区域的总大小 25 printf("bok_dat_title:%d \n", sizeof(bok_dat_p->title)); 26 printf("bok_dat_price:%d \n", sizeof(bok_dat_p->price)); 27 printf("bok_dat_isbn:%d \n", sizeof(bok_dat_p->isbn)); 28 29 free(bok_dat_p);//释放内存 30 return 0; 31 }
你可以复制到 https://www.runoob.com/try/runcode.php?filename=helloworld&type=c 进行在线测试。
当然,下面这个更简单,是不是真的很简单呢?(从教材读到,会产生大量的内存碎片,这些碎片是无法被系统使用的,大问题!,而CONTIKI很好处理了这些问题)
#include <stdio.h> #include <stdlib.h>//利用malloc()进行动态内存分配 int main() { int *int_p;
int_p = malloc(sizeof(int));//为int_p分配内存区域,int一般是4字节吧,看系统情况 if(!int_p)return 0;//如果申请失败就直接退出
*int_p = 0x0f0f0f0f;//向内存块写入值 free(int_p);//释放内存
return 0; }
在OS里面,内存是有限的 宝贵的公共资源,只有在任务运行的时候,动态分配才是可行方案;举个例子,当你有100进程,但是只有30个进程在运行,
如果100个都分配好的话,是不是白白浪费SRAM了?话说占着毛坑不拉X,就是这个道理!!
时间:2021-01-12
把\os\lib内的memb.h进行爆光:
/** * Declare a memory block.声明内存块
* * \param:name给内存块取个名字, memb_init(), memb_alloc() and memb_free()使用. * * \param:structure内存块保存的结构的名称 * * \param:num内存块总数,以字节为单位 * */ #define MEMB(name, structure, num) \ static bool CC_CONCAT(name,_memb_used)[num]; \ static structure CC_CONCAT(name,_memb_mem)[num]; \ static struct memb name = {sizeof(structure), num, \ CC_CONCAT(name,_memb_used), \ (void *)CC_CONCAT(name,_memb_mem)} struct memb { unsigned short size; unsigned short num; bool *used; void *mem; }; /** * 初始化用MEMB()声明的内存块。 * * \param 一组先前用MEMB()声明的内存块。. */ void memb_init(struct memb *m); /** * 从用MEMB()声明的内存块中分配一个内存块。 * * \param 一组先前用MEMB()声明的内存块。. */ void *memb_alloc(struct memb *m); /** * 从先前用MEMB()声明的内存块中释放内存块。 * * \param 一组先前用MEMB()声明的内存块。 * * \param ptr指向要释放的内存块的指针。 * * \return 如果成功释放,错误代码应为 0,如果指针"ptr"未指向合法内存块,则为 -1。 */ int memb_free(struct memb *m, void *ptr); /** * 检查给定地址是否在先前用MEMB()声明的存储区之内。 * * \param 一组先前用MEMB()声明的内存块。 * * \param ptr指向要检查的地址的指针 * * \return 如果地址是存储块的一部分,则为1;否则为0。 否则为0 */ int memb_inmemb(struct memb *m, void *ptr); /** * 计数可用内存块 * * \param 一组先前用MEMB()声明的内存块。 * * \return 空闲(可用)内存块的数量 */ int memb_numfree(struct memb *m);
哈哈,看到这里,好像知道怎么使用CONTIKI NG的MEMB内存分配了。要好好试验加以掌握它!
接下来,让我们测试一下,CONTIKI NG的MEMB静态内存分配:
/*------------------------MEMB应用--------------------------------------------*/ #include "lib/memb.h"//加载静态内存库 PROCESS(MEMB_process, "MEMB process"); struct connection{ // 结构体,只有2个成员socket,实际应用中可能是多个 char ID; int socket; }; MEMB(connections, struct connection, sizeof(struct connection)/4); // 申请一块connections内存 ,附合struct connection的大小 PROCESS_THREAD(MEMB_process, ev, data)//MEMB的process实现 { PROCESS_BEGIN(); struct connection *pr; //对应的指针 while(1) { memb_init(&connections); //初化内存块,就是SET为0值,不能是垃圾值或以前旧值 pr = memb_alloc(&connections); //给pr分配内存 if(pr == NULL){ //检查是不是分配成功 return NULL; //不成功,返回NULL } pr->socket = 0xffff;//成功就附值进行测试 printf("conn-socket:0x%x \n", pr->socket);//CONN的值是:??测试一个成员socket,实际应用中可能是多个 printf("memb_numfree1:%d \n", memb_numfree(&connections));//connections内存块,还有多少可用数量?? memb_free(&connections, pr);//释放内存 pr = NULL; //pr为空指针。 printf("memb_numfree2:%d \n", memb_numfree(&connections));//释放后,还有多少可用数量?? PROCESS_EXIT(); //退出进程,释放资源 } PROCESS_END(); } /*------------------------所有自启动的测试PROCESSES---------------------------*/ AUTOSTART_PROCESSES( &MEMB_process );
测试效果如下:
从执行效果来看是正常的。在32位单片机中,一份内存块就是32BIT的,就是四个字节,我们可以看到,
为了内容对齐,一个char也是按照32BIT来分配的。
关于heapmem.h动态分配器的,来看看CONTIKI 作者的原话:
* \note This module does not contain a corresponding function to the * standard C function calloc(). * * \note Dynamic memory should be used carefully on * memory-constrained, embedded systems, because fragmentation * may be induced through various allocation/deallocation * patterns, and no guarantees are given regarding the * availability of memory.
如果你是在PC端,跑LINUX系统,可以用一下heapmem分配器,但是受限的嵌入式系统中,不建议使用的。
哪么明白了(内存碎片是个麻烦事),这个heapmem只作少量了解,直接跳过它就好了。