Zephyr OS 核心篇 核心鍊錶

2021-07-23 11:10:30 字數 3159 閱讀 8792

zephyr os 所有的學習筆記已託管到 github,csdn 部落格裡的內容只是 github 裡內容的拷貝,因此鏈結會有錯誤,請諒解。

最新的學習筆記請移步 github:

本文先簡單地介紹了一些內聯函式的知識,然後再詳細分析 zephyr os 核心中的鍊錶的原始碼。

在 zephyr os 中,實現了乙個雙鏈表,其**位於標頭檔案 inclue/misc/dlist.h 中。

居然將函式實現在標頭檔案中!!再仔細一看,這些函式不是普通的函式,而是內聯函式!

為什麼?這樣有什麼好處?在網上搜了一通,總結如下:

內聯函式 vs 巨集:

內聯函式 vs 普通函式:

內聯函式的缺點:

在 zephyr os 的原始碼中,還會看到另外一套鍊錶,位於 net/ip/contiki/os/list.[ch]。這套鍊錶是移植於contiki,只在ip協議棧中有使用。

struct _dnode ;

union ;

};

第一眼就蒙了,為什麼節點的定義裡面居然有兩個聯合體。直到看到後來,恍惚間想明白了。zephyr os 中對該結構體使用 tpyedef 定義了兩種型別:

typedef

struct _dnode sys_dlist_t;

typedef

struct _dnode sys_dnode_t;

sys_dlist_t 定義了乙個雙鏈表,sys_dnode_t 定義了乙個節點。在使用 sys_dlist_t 時,使用的是結構體中的 head, tail 兩個成員;在使用 sys_dnode_t 時,使用的是結構體中的 next, prev 兩個成語。

其實我們可以對上面的**展開成兩個結構體:

typedef

struct _dnode sys_dnode_t;

typedef

struct _dlist sys_dlist_t;

有人可能會被鍊錶和節點兩個概念搞暈了,比如曾經的我。我們只需要記住一點,在使用鍊錶的時候,我們都是先定義乙個鍊錶,然後往煉表裡進行新增節點、刪除節點、查詢節點等操作。比如:

sys_dlist_t mylist;               // 定義鍊錶

sys_dlist_init(&mylist); // 鍊錶初始化

sys_dnode_t mynode1, mynode2; // 定義節點

... // 對節點初始化

static inline

void sys_dlist_init(sys_dlist_t *

list)

理解了前面所說的東西,再看具體的**實現,so easy.

進行鍊錶的初始化,此時鍊錶是空的,沒有任何節點,所以將 head, tail 兩個指標都指向 list 自身。

static

inline

int sys_dlist_is_head(sys_dlist_t *list, sys_dnode_t *node)

static

inline

int sys_dlist_is_tail(sys_dlist_t *list, sys_dnode_t *node)

static

inline

int sys_dlist_is_empty(sys_dlist_t *list)

static inline sys_dnode_t *sys_dlist_peek_head(sys_dlist_t *

list)

先判斷鍊錶是否為空,如果為空,則返回 null,否則返回頭結點。所以在使用才函式時,需要判斷返回值是否為 null,再做處理。

static inline sys_dnode_t *sys_dlist_peek_next(sys_dlist_t *

list,

sys_dnode_t *node)

先判斷傳入的節點是不是鍊錶的尾節點,如果是,則返回 null,否則返回下乙個節點。所以在使用才函式時,需要判斷返回值是否為 null,再做處理。

static inline

list, sys_dnode_t *node)

static inline

void sys_dlist_prepend(sys_dlist_t *

list, sys_dnode_t *node)

static inline

void sys_dlist_insert_after(sys_dlist_t *

list,

sys_dnode_t *insert_point, sys_dnode_t *node)

else

}

static inline

void sys_dlist_insert_before(sys_dlist_t *

list,

sys_dnode_t *insert_point, sys_dnode_t *node)

else

}

static inline

void sys_dlist_remove(sys_dnode_t *node)

static inline sys_dnode_t *sys_dlist_get(sys_dlist_t *

list)

node =

list

->head;

sys_dlist_remove(node);

return node;

}

取出頭節點後將其重煉表中刪除。

核心hlist鍊錶

出處 核心中的定義 struct hlist head struct hlist node 這個資料結構與一般的hash list資料結構定義有以下的區別 1 首先,hash的頭節點僅存放乙個指標,也就是first指標,指向的是list的頭結點,沒有tail指標也就是指向list尾節點的指標,這樣的...

linux核心鍊錶

鍊錶是一種常用的資料結構,它通過指標將一系列資料節點連線成一條資料鏈。相對於陣列,鍊錶具有更好的動態性,建立鍊錶時無需預先知道資料總量,可以隨機分配空間,可以高效地在鍊錶中的任意位置實時插入或刪除資料。鍊錶的開銷主要是訪問的順序性和組織鏈的空間損失。一 鍊錶結構 單鏈表結構如下 雙鏈表結構如圖 st...

linux核心鍊錶

include include struct list head struct mylist void list add struct list head new,struct list head prev,struct list head next void list add tail struc...