Android中的雙向鏈表

來源:互聯網
上載者:User

標籤:

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 getthe struct for this entry137 * @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中的雙向鏈表

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.