鏈表的結構體如下:

<鏈表的初始化>
方法1:

實例:

方法2:

定義和初始化一步到位,實例:

方法2:
使用函數的方式初始化

<往鏈表中添加成員>


list_add傳入new,和head。當head還未加入其它元素的情況下,head->next的值是一個地址,該地址指向head本身:

繼續往添加成員:

添加成員不只有一個方向,還可以不斷的往HEAD后面追加(①->②,添加③,可以這樣①->②->③,也可以①->③->②,①這里代表head):

<鏈表中成員的刪除>


第一種情況 第二種情況


把自己從原來的鏈表中刪除,加入到新的鏈表中

<鏈表中的判斷>
判斷鏈表是否為空

判斷該成員是否為鏈表的最后一項

<鏈表中的使用>
前面看到的是鏈表自己在“玩”自己,那如何使用鏈表呢?看下面這個宏(這個宏完全可以用在其它情景):

這個宏獲取含有
struct list_head
成員的結構體對象首地址
了解list_entry前需要先分析下container_of
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) //該宏的作用是獲取結構體成員的相對偏移值
/*
* ptr : 成員的指針
* type :結構體類型
* member :在結構體中成員的名稱
* 返回該成員所在的結構體變量的指針
*/
#define container_of(ptr, type, member) ({ \
const typeof(((type *)0)->member)*__mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type, member)); })
const typeof(((type *)0)->member)*__mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type, member)); })
typeof:獲取括號內對象的類型,需要包含頭文件stddef.h
備注:typeof 是 GNU C 標准里特有的擴展,標准的 ISO C 並沒有這個關鍵字,編譯加入了一個 -std=c90 的選項改成 -std=gnu90
實例如下:

結果:

<
鏈表的遍歷
>

pos是臨時使用的struct list_head指針變量,從鏈表head(head不一定是鏈表頭)中遍歷head后面的所有成員。

也可以換個方向遍歷

關於prefetch的解釋如下,未完全明白!
1.有一個共識是:程序訪問的變量如果都能在系統內存cache中則能提升性能,prefetch是內核中一個預熱內存函數,這樣下次遍歷時就能高效命中內存cache,從而提升程序性能。
2.上面的代碼中遍歷鏈表時下次訪問的內存為pos->next,故在每次遍歷時對pos->next進行預熱,從而提升性能。
2.上面的代碼中遍歷鏈表時下次訪問的內存為pos->next,故在每次遍歷時對pos->next進行預熱,從而提升性能。
下面的方法是使用最多的,遍歷鏈表取出一個個包含struct list_head成員的結構體對象的首地址

使用實例:

示意圖如下:

鏈表的其它接口暫不分析,有需求再看!