Linux利用list head結構實現雙向鍊錶

2021-08-04 06:32:34 字數 1610 閱讀 9119

**

通常實現雙向鍊錶的資料結構:

struct list_node1;

struct list_node2;

……

對於每一種資料結構都定義了其特定的實現鍊錶的結構和對應的方法(add/del)操作鍊錶;

但對於具有大量不同資料結構,都要使用鍊錶的系統中,如果為每一種資料結構定義特定的結構,和操作方法,

無疑使**變得重複和臃腫,需要實現一種通用的雙向鍊錶方法,對各種資料結構都能適用。

c語言中又沒有c++裡面的模板,該如何實現呢?

linux核心中大量使用如下資料結構實現雙向鍊錶:

struct list_head ;
如果需要有某種資料結構的雙向佇列,就在這種結構內部放乙個list_head資料結構成員。

struct kobject
形成了如下結構:

如何通過kobject 鍊錶結構中的 list_head 成員entry訪問下乙個成員呢?

系統提供了巨集list_entry:

#define list_entry(ptr, type, member) \ 

((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))

//訪問鍊錶成員

kobject *obj = objlist;

kobject *nextobj = (kobject *)list_entry(obj->entry->next,struct kobject,entry);

這個list_entry是什麼道理呢:ptr:是指向當前kobject結構物件中的資料成員entry,(char *)(ptr):entry成員位址 ——addra

(unsigned long)(&((type *)0)->member)):將位址0轉化為型別為type(struct kobject )物件,取member(entry)成員的位址——addrb

(type *)(addra - addrb):得到kobject結構物件的首位址,轉化為kobject物件。

這裡需要關注的就是addrb:將位址0轉化為型別為type(struct kobject )物件,取member(entry)成員的位址。

表示當struct kobject 物件首位址為0時,得到成員member(entry)的位址,相對首位址的偏移位址。

通過struct kobject 物件中member(entry)的位址 ,以及相對首位址的偏移量,就能計算出struct kobject 物件的首位址。

如下結構:

充分利用了c語言中直接操作記憶體位址的特性。

Linux 核心list head 學習

在linux核心中,提供了乙個用來建立雙向迴圈鍊錶的結構 list head。雖然linux核心是用c語言寫的,但是list head的引入,使得核心資料結構也可以擁有物件導向的特性,通過使用操作list head 的通用介面很容易實現 的重用,有點類似於c 的繼承機制 希望有機會寫篇文章研究一下c...

Linux 核心list head 學習

在linux核心中,提供了乙個用來建立雙向迴圈鍊錶的結構 list head。雖然linux核心是用c語言寫的,但是list head的引入,使得核心資料結構也可以擁有物件導向的特性,通過使用操作list head 的通用介面很容易實現 的重用,有點類似於c 的繼承機制 希望有機會寫篇文章研究一下c...

Linux 核心list head 學習

linux 核心list head 學習 一 在linux 核心中,提供了乙個用來建立雙向迴圈鍊錶的結構 list head 雖然linux 核心是用 c語言寫的,但是 list head 的引入,使得核心資料結構也可以擁有物件導向的特性,通過使用操作 list head 的通用介面很容易實現 的重...