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<stdio.h>
#include<stddef.h>

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

Android中的双向链表,布布扣,bubuko.com

时间: 2024-12-21 21:47:01

Android中的双向链表的相关文章

Android中的ueventd

前言 与Linux相同,Android中的应用程序通过设备驱动访问硬件设备.设备节点文件是设备驱动的逻辑文件,应用程序使用设备节点文件来访问驱动程序. 在Linux中,运行所需的设备节点文件被被预先定义在"/dev"目录下.应用程序无需经过其它步骤,通过预先定义的设备节点文件即可访问设备驱动程序. 但根据Android的init进程的启动过程,我们知道,Android根文件系统的映像中不存在"/dev"目录,该目录是init进程启动后动态创建的. 因此,建立Anro

Android中的数据结构

数据结构在Android中也有着大量的运用,这里采用数据结构与源代码分析相结合,来认识Android的数据结构 线性表 线性表可分为顺序存储结构和链式存储结构 顺序存储结构-ArrayList 通过对源代码的产看得知,ArrayList继承自AbstractList,实现了多个接口,其中List里面就实现了常用的一些操作,包括增删改查清除大小等等 public class ArrayList<E> extends AbstractList<E> implements List<

谈谈-Android中的接口回调技术

Android中的接口回调技术有很多应用的场景,最常见的:Activity(人机交互的端口)的UI界面中定义了Button,点击该Button时,执行某个逻辑. 下面参见上述执行的模型,讲述James对Android接口回调技术的理解(结合前人的知识和自己的实践). 使用一个比喻很形象地说明:客户端有个疑问打电话请教服务端,但服务端无法现场给出解答,相互之间约定:服务端一旦有答案,使用电话的方式反馈给客户端. 以上有三个主体:客户端.服务端和接口(方式). 接口回调的原理框图说明: Demo界面

关于android中事件传递和分发的一些小理解

android中 当我们的手指触摸屏幕将产生一个事件, (假设 这个过程中如果没有显示的去拦截该事件的话)   这个事件会逐级传递到视图的最底层,即使在中间某些视图会响应这个事件( 这个视图也不会去消费这个事件),     仍然是会传递到底层(底层不响应该事件),然后再由底层回传到顶层,在传回顶层的过程中 ,   原先会响应该事件的视图才会去消费这个事件 例如在左图中                                 A                               

浅谈android中仅仅使用一个TextView实现高仿京东,淘宝各种倒计时

今天给大家带来的是仅仅使用一个TextView实现一个高仿京东.淘宝.唯品会等各种电商APP的活动倒计时.最近公司一直加班也没来得及时间去整理,今天难得休息想把这个分享给大家,只求共同学习,以及自己后续的复习.为什么会想到使用一个TextView来实现呢?因为最近公司在做一些优化的工作,其中就有一个倒计时样式,原来开发的这个控件的同事使用了多个TextView拼接在一起的,实现的代码冗余比较大,故此项目经理就说:小宏这个就交给你来优化了,并且还要保证有一定的扩展性,当时就懵逼了.不知道从何处开始

Android中监听ListView滑动到底部

Android中的应用就是ListView中向下滑动加载更多的功能,不要再onScroll方法中进行判断,那样当滑动到底部的时候,可能我们需要触发点什么事件,比如加载更多.隐藏某个控件等等. 第一种方法是直接滑动到底部就触发 listview.setOnScrollListener(new OnScrollListener(){       @Override       public void onScrollStateChanged(AbsListView view, int scrollS

Android基础入门教程——8.1.3 Android中的13种Drawable小结 Part 3

Android基础入门教程--8.1.3 Android中的13种Drawable小结 Part 3 标签(空格分隔): Android基础入门教程 本节引言: 本节我们来把剩下的四种Drawable也学完,他们分别是: LayerDrawable,TransitionDrawable,LevelListDrawable和StateListDrawable, 依旧贴下13种Drawable的导图: 1.LayerDrawable 层图形对象,包含一个Drawable数组,然后按照数组对应的顺序来

Android基础入门教程——8.1.2 Android中的13种Drawable小结 Part 2

Android基础入门教程--8.1.2 Android中的13种Drawable小结 Part 2 标签(空格分隔): Android基础入门教程 本节引言: 本节我们继续来学习Android中的Drawable资源,上一节我们学习了: ColorDrawable:NinePatchDrawable: ShapeDrawable:GradientDrawable!这四个Drawable~ 而本节我们继续来学习接下来的五个Drawable,他们分别是: BitmapDrawable:Insert

Android中微信抢红包插件原理解析和开发实现

一.前言 自从去年中微信添加抢红包的功能,微信的电商之旅算是正式开始正式火爆起来.但是作为Android开发者来说,我们在抢红包的同时意识到了很多问题,就是手动去抢红包的速度慢了,当然这些有很多原因导致了.或许是网络的原因,而且这个也是最大的原因.但是其他的不可忽略的因素也是要考虑到进去的,比如在手机充电锁屏的时候,我们并不知道有人已经开始发红包了,那么这时候也是让我们丧失了一大批红包的原因.那么关于网络的问题,我们开发者可能用相关技术无法解决(当然在Google和Facebook看来的话,他们