鏈表簡介
鏈表是一種常用的數據結構,它通過指針將一系列數據節點連接成一條數據鏈。相對於數組,鏈表具有更好的動態性,建立鏈表時無需預先知道數據總量,可以隨機分配空間,可以高效地在鏈表中的任意位置實時插入或刪除數據。鏈表的開銷主要是訪問的順序性和組織鏈的空間損失。
鏈表的種類有很多:
單向鏈表、雙向鏈表、循環鏈表等等。
Linux內核鏈表屬於雙向循環鏈表。
傳統鏈表與Linux內核鏈表的區別:
傳統鏈表一個節點包含數據域和指針域,指針域指向的位置往往時下一個或上一個節點的開始位置。傳統鏈表的一個缺陷就是每個節點的數據域的數據類型是相同的,用戶無法給每個節點安排不同的數據類型。
Linux內核鏈表解決了上述缺陷,它的指針域的指針指向的位置時下一個或上一個節點指針域的開始位置,這樣用戶可以任意指定數據域的數據類型。指針域的類型時統一的。
內核鏈表
結構:
struct list_head
{
struct list_head *next, *prev;
};
list_ head 結構包含兩個指向 list_head 結構的指針prev和next,由此可見,內核的鏈表具備雙鏈表功能,實際上,通常它都組織成雙向循環鏈表。
函數:
1、 INIT_ LIST_HEAD:創建鏈表
2、 list_ add:在鏈表頭插入節點
3、 list_ add_tail:在鏈表尾插入節點
4、 list_ del:刪除節點
5、 list_ entry:取出節點
6、 list_ for_ each:遍歷鏈表
代碼編寫
mylist.c文件
#include <linux/init.h>
#include <linux/module.h>
#include <linux/list.h> //使用內核鏈表需要的頭文件
struct score//自定義結構體,學生的學號和成績
{
int number;//數據域
int english;
int math;
struct list_head list;//指針域
};
struct list_head score_head;//定義鏈表頭結點
struct score stu1, stu2, stu3, *tmp;
struct list_head *pos; //用於遍歷鏈表的指針
static int mylist_list()
{
//創建鏈表
INIT_LIST_HEAD(&score_head); //創建鏈表,參數是頭結點指針域的地址
stu1.number = 1;
stu1.english = 1;
stu1.math = 1;
stu2.number = 2;
stu2.english = 2;
stu2.math = 2;
stu3.number = 3;
stu3.english = 3;
stu3.math = 3;
//插入節點
list_add_tail(&(stu1.list), &score_head);//在鏈表尾插入節點,
list_add_tail(&(stu2.list), &score_head);//參數1節點指針域地址
list_add_tail(&(stu3.list), &score_head);//參數2頭結點指針域地址
//遍歷鏈表
list_for_each(pos, &score_head)
//第一個參數是list_head指針,第二個參數是頭結點地址,要使用大括號,是for循環
//隨着遍歷的進行,pos指針分別指向每一個節點
{
//取出節點,注意:返回值是節點指針
tmp = list_entry(pos, struct score, list);
//參數1:光標指針,參數2:節點類型,參數3:節點指針域名字
printk("第 %d 號學生\n", tmp->number);
printk("英語成績:%d\n", tmp->english);
printk("數學成績:%d\n", tmp->math);
printk("\n");
}
return 0;
}
static void mylist_exit()
{
//刪除節點,參數爲節點的指針域地址
list_del(&(stu1.list));
list_del(&(stu2.list));
list_del(&(stu3.list));
}
module_init(mylist_list);
module_exit(mylist_exit);
makefile 文件:
obj-m := mylist.o
KDIR := /home/ARM_Linux/system2/season4/First/part3/linux-ok6410
all:
make -C $(KDIR) M=$(PWD) modules CROSS_COMPILE=arm-linux- ARCH=arm
clean:
rm -f *.o *.ko *.order *.symvers *.bak *.mod.c