zephyr os 所有的學習筆記已託管到 github,csdn 部落格裡的內容只是 github 裡內容的拷貝,因此鏈結會有錯誤,請諒解。本文先簡單地介紹了一些內聯函式的知識,然後再詳細分析 zephyr os 核心中的鍊錶的原始碼。最新的學習筆記請移步 github:
在 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...