Contiki memb

Contiki提供了三种内存分配机制:memb机制、mmem机制和标准C语言库中的堆内存分配机制。memb最常使用,mmem极少使用,而使用堆内存分配是一件危险的事情。这篇日志讲解memb

memb库提供了一系列内存块管理函数。内存块在静态内存区中被分配为具有固定尺寸的数组。
先把里面的例子搬出来

 #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);
 }

先来看看MEMB()宏源码:

#define MEMB(name, structure, num)\ 
        static char CC_CONCAT(name,_memb_count)[num]; \
        static structure CC_CONCAT(name,_memb_mem)[num]; \
        static struct memb name = {sizeof(structure), num, \
                        CC_CONCAT(name,_memb_count), \
                        (void *) CC_CONCAT(name,_memb_mem)}
struct memb {
    unsigned short size;
    //num表示可以存放的结构体个数,由于用short声明,表明最多只能控制127个结构体
    unsigned short num;
    char *count;
    void *mem;
};

先借用上例中的代码把这个宏展开来看看:

struct connection {
   int socket;
 };
 MEMB(connections, struct connection, 16);

展开后的代码:

//char数组,估计用于指向实际内存地址 
static char connections_memb_count[16];
//结构体数组,结构体实际存放的地方 
static struct connection connections_memb_mem[16];
static struct memb connections =
{
  sizeof(struct connection), //这里可以假设为2,一个int的大小 
  16, //结构体总个数 
  connections_memb_count, //指向指针数组
  (void *)connections_memb_mem //指向结构体实际存放的地方
 }

这个东西讲出来挺拗口,来张图就一目了然了:

内存分配---memb

小结一下:有一个结构体connection,我们需要分配一段内存存放16个connection。使用MEMB实际上已经分配了这16个空间了,需要注意的是static关键字表明,它们被分配到了静态内存区。那么现在还有一个疑问,connections_memb_count[16]里面存放什么东西?有何用,得继续往下研究。

下面来看下memb_init原型:

void memb_init(struct memb *m)
{ 
  //把char数组里面的元素全部初始化为0
  memset(m->count, 0, m->num);
  //把结构体所占内存全部初始化为0    
  memset(m->mem, 0, m->size * m->num);
}

memset()函数是C语言标准库函数,memb_init函数就是把所占内存全部清0。

memb_alloc原型:

void *memb_alloc(struct memb *m)
{
      int i;
      for(i = 0; i < m->num; ++i)
      {
            if(m->count[i] == 0)   //为0表示此空间并未使用
           {
                  ++(m->count[i]); //等同于m->count[i]=1;                  
             //返回分配的结构体空间首地址                  
             return (void *)((char *)m->mem + (i * m->size));
            }
      }
      /* 能走到这里说明没有多余空间,分配失败了,标志为返回NULL */
      return NULL;
}

现在终于明白connections_memb_count[16]的作用了,可以把它理解为标志位。某段结构体空间已用则标上1,某段结构体空间空闲则标上0。如果象C#那样有BitArray这样的数据结构,完全可以用一个位来存放这样的标志,现在用8个位存放一个标志,有点浪费空间了。不过如果用位运算,访问的时候需要另外声明函数返回标志,有些麻烦。

char[16]实际上和struct[16]一一对应,在char[16]中只要找到一个为0的元素,就说明它所对应的struct空间空闲,这时返回struct空间首地址作为memb_alloc函数的返回值。

memb_free原型:

char memb_free(struct memb *m, void *ptr)
{
      int i;
      char *ptr2;
      ptr2 = (char *)m->mem;
      for(i = 0; i < m->num; ++i)
      {
            if(ptr2 == (char *)ptr)   //找到释放的空间             
            {
                  if(m->count[i] > 0)
                  {
                        --(m->count[i]); //设标志位为0 
                 }
                  return m->count[i]; //返回0             
            }
            ptr2 += m->size; //指向下一块空间      
      }
      return -1; //没找到相应空间返回-1 
}

memb_free用于释放空间,实际上只是把相应的标志位设为0,结构体空间原来的数据并未清除,这是不是有些危险?所以在使用memb的时候一定要注意,里面的结构体每个成员在使用前必须要全部赋值,否则会有出错的可能。

**int memb_inmemb(struct memb m, void ptr)

求证一个指针是否在memb之中

*int memb_numfree(struct memb m)

返回memb的空余空间的个数

最后来个总结吧,memb这东西我个人感觉更象是一个线程池之类的东西。例如我们在写程序时,需要多次同时用到一个结构体类型,每个结构体每次用的时间都不确定,这篇文章开头用的socket就是个很典型的例子。这时就可以使用memb进行统一管理。memb的作用可以作个比喻:学校有个体育馆,里面有6个羽毛球场地,学生要打羽毛球就必须到体育馆去,打完球后,空出来的场地可以让别的同学继续打,如果没有场地了则必须等到有人打完后才能轮到你。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,744评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,505评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,105评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,242评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,269评论 6 389
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,215评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,096评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,939评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,354评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,573评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,745评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,448评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,048评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,683评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,838评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,776评论 2 369
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,652评论 2 354

推荐阅读更多精彩内容