Chinaunix首页 | 论坛 | 博客
  • 博客访问: 393219
  • 博文数量: 87
  • 博客积分: 1171
  • 博客等级: 少尉
  • 技术积分: 1068
  • 用 户 组: 普通用户
  • 注册时间: 2012-09-19 14:34
文章分类

全部博文(87)

文章存档

2014年(10)

2013年(24)

2012年(53)

我的朋友

分类: 嵌入式

2012-10-16 10:45:08

 

 下面XX YY表示XX层高于YY层,且是相邻层,其具体代表参考分享的一篇博客,在他的基础上,进行了自己的总结。

  http://blog.chinaunix.net/uid-23117778-id-3374517.html

YY_callback;

XX_open(XX_conn,channel,XX_callback);
{
   YY_open(YY_conn,channel,YY_callback)
}

1,上层的XX__conn结构包含下层的YY_conn结构。

2,每一层XX_open函数打开本层XX_callback函数。

3,下一层YY_callback函数,是上一层的XX_open函数那里定义。

4,每一层XX_open初始化关于本层XX_conn的一些结构成员初始化(其中重要的一个就是,初始化本层XX_conn中的XX_callback成员);附加本层属性;并通过YY_open,将XX_conn->YY_conn传递下去;继续初始化

5,channel是一直传递下去的,到channel_open,将此channel加入到全局的channel_list结构中

无论是接收方,还是发送方都应该先初始化这些结构,每层(如果需要的话)都将需要的属性加入到channel结构中(当然只保存最高层的属性,结构体中是一个指针,而不是一个数组):
struct channel {
  struct channel *next;
  uint16_t channelno;
  const struct packetbuf_attrlist *attrlist;
  uint8_t hdrsize;
};

struct packetbuf_attrlist {
  uint8_t type;
  uint8_t len;
};


由结构可知,每个channel都有一个packetbuf_attrlist[]结构,每层将对应的属性添加到这个数组中;在XX_open中调

用 channel_set_attributes(channel, attributes);
1,此API会调用c = channel_lookup(channelno);来找到该channel对应的结构体;
2,attributes 是一个
static const struct packetbuf_attrlist attributes[] =
  {
    BROADCAST_ATTRIBUTES PACKETBUF_ATTR_LAST
  };

static结构的数组,也就是根据不同层的.c文件,都会有属于自己文件的attributes[]来标识自己的层的属性。

这样,从最上层到最下层的初始化过程中,将各层结构体成员(控制信息);回调函数(处理函数定义);属性(头属性说明)进行了对应的设置。


通道属性问题:Rime不是通过改变头的某些位来表示一些特殊含义,而是通过头属性来显示。

 

 

 

   每一层XX_open函数首先是调用YY_open一直到最底层,然后将通道结构加入链表。看似是上层先初始化的,实际上是倒过来进行的。

  这个图不是很清醒,但是已经明确的指出了初始化的整个过程,实际上是下层早于上层完成初始化。

   目的应该是:最上层打开通道的时候,此时通道还没有真正初始化,通道的结构实体是在abc_conn结构体中的,所以必须先初始化此通道,上层才能将对应的属性附加到此通道上。

 

  关于属性的设置问题:

  1. void channel_set_attributes(uint16_t channelno, const struct packetbuf_attrlist attrlist[])
  2. {
  3.   struct channel *c;
  4.   c = channel_lookup(channelno);
  5.   if(c != NULL)
  6.   {
  7.     c->attrlist = attrlist;
  8.     c->hdrsize = chameleon_hdrsize(attrlist);
  9.   }
  10. }
  11. struct packetbuf_attrlist
    {
  12.   uint8_t type;
      uint8_t len;
    };
  13. 看到c->attrlist是直接赋值本层attrlist结构的(这个结构是定义为static类型的,限制了作用域),并调用了chameleon_hdrsize函数来计算其所有属性的总长度。
     http://blog.chinaunix.net/uid-9112803-id-3269506.html
         这篇博文对里面进行深入的剖析,但是感觉有些问题还是没有说清楚,毕竟看了源码就会知道,这里面有太多的宏,跟踪下去一会就晕菜了。但是可以得出一个大致的结论:
            由于RIme通信分层的,它的通信并不要求没个层都必须参加,由下图可以看出:

          既然不许要所有层都参加,那属性的设置干脆就根据层来设置,比如只用到最高层A层,那么只需要A层的属性赋值给该通道就行了,而在A层下面的B层,C层即使有属性设置,也会被最高层的A层属性所覆盖。生成最终的通道属性,而不是一个累计的过程。如果最高层是B层,那么通道的属性通过覆盖到C层的属性,来设置,即时B层的属性。

         

            属性的理解:属性结构体可以看出来,其实是一个8位图和一个长度变量,8位位图可以表示256种组合,所以协议属性的要求完全可以这个位图来标识。至于结构体里面的长度成员还没搞清楚是什么作用,宏太深了,感觉没必要都跟通,大致清楚就行了,编程的时候直接调用就行了,不用你自己控制这些属性(阿Q一下O(∩_∩)O。。。)。

        阅读(1325) | 评论(2) | 转发(0) |
        给主人留下些什么吧!~~

        hnylcxq2013-11-25 16:19:41

        joven_cumt:你好,我有一点疑问,如果隔层使用协议栈。回调函数和open函数如何连接起来呢???如何配置选择那一层呢?自己手动修改函数吗?
        还有就是,即便是每一层都使用了,我见到的contiki自带例子都是实现了最高层的进程和函数。中间层的回调是不是就不用了,默认为空。

        你跟踪代码会看到,你在最上层进行设置,其他的设置,程序都是依次调用相应的函数,完成下层的配置的。

        回复 | 举报

        joven_cumt2013-09-02 22:13:38

        你好,我有一点疑问,如果隔层使用协议栈。回调函数和open函数如何连接起来呢???如何配置选择那一层呢?自己手动修改函数吗?
        还有就是,即便是每一层都使用了,我见到的contiki自带例子都是实现了最高层的进程和函数。中间层的回调是不是就不用了,默认为空。