android中定义链表,Android中的双向链表

1.看源码必须搞懂Android的数据结构。在init源代码中双向链表listnode使用很多,它只有prev和next两个指针,没有任何数据成员。这个和linux内核的list_head如出一辙,由此可见安卓深受linux内核的影响的。本来来分析一下这个listnode数据结构。

这里需要考虑的一个问题是,链表操作都是通过listnode进行的,但是那不过是个连接件,如果我们手上有个宿主结构,那当然知道了它的某个listnode在哪里,从而以此为参数调用list_add和list_del函数;可是,反过来,当我们顺着链表取得其中一项的listnode结构时,又怎样找到其宿主结构呢?在listnode结构中并没有指向其宿主结构的指针啊。毕竟,我们我真正关心的是宿主结构,而不是连接件。对于这个问题,我们举例内核中的list_head的例子来解决。内核的page结构体含有list_head成员,问题是:知道list_head的地址,如何获取page宿主的地址?下面是取自mm/page_alloc.c中的一行代码:

page = memlist_entry(curr, struct page, list);

这里的memlist_entry将一个list_head指针curr换算成其宿主结构的起始地址,也就是取得指向其宿主page结构的指针。读者可能会对memlist_entry()的实现感到困惑。

#define memlist_entry list_entry

而list_entry定义则在include/linux/list.h中

135 /**

136 * list_entry get

the struct for this entry

137 * @ptr: the &struct list_head pointer.

138 * @type: the type of the struct this is embedded in.

139 * @member: the name of the list_struct within the struct.

140 */

141 #define list_entry(ptr, type, member) 142 ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))

这样我们应该就明白了,curr是一个page结构内部成分list的地址,而我们所需要的却是那个page结构本身的地址,所以要从curr减去一个偏移量,即成分list在page内部的位移量。那么这个位移量怎么求?&((struct page*)0)->list就表示当结构page正好在地址0上时其成分list的地址,这就是所求的偏移量。

2.测试代码

#include

#include

typedef struct _listnode

{

struct _listnode *prev;

struct _listnode *next;

}listnode;

#define node_to_item(node,container,member) (container*)(((char*)(node))-offsetof(container,member))

//向list双向链表尾部添加node节点,list始终指向双向链表的头部(这个头部只含有prev/next)

void list_add_tail(listnode *list,listnode *node)

{

list->prev->next=node;

node->prev=list->prev;

node->next=list;

list->prev=node;

}

//定义一个测试的宿主结构

typedef struct _node

{

int data;

listnode list;

}node;

int main()

{

node n1,n2,n3,*n;

listnode list,*p;

n1.data=1;

n2.data=2;

n3.data=3;

list.prev=&list;

list.next=&list;

list_add_tail(&list,&n1.list);

list_add_tail(&list,&n2.list);

list_add_tail(&list,&n3.list);

for(p=list.next;p!=&list;p=p->next)

{

n=node_to_item(p,node,list);

printf("%d\n",n->data);

}

return 0;

}

原文:http://blog.csdn.net/getnextwindow/article/details/37761505

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值