内核链表
以下內容源于朱有鵬《物聯網大講堂》課程的學習,如有侵權,請告知刪除。
一、linux內核鏈表
1、普通鏈表的數據區域的局限性
- 之前定義數據區域時直接int data,我們認為我們的鏈表中需要存儲的是一個int類型的數。但是實際上現實編程中鏈接中的節點不可能這么簡單,而是多種多樣的。
- 一般實際項目中的鏈表,節點中存儲的數據其實是一個結構體,這個結構體中包含若干的成員,這些成員加起來構成了我們的節點數據區域。
2、一般性解決思路:即把數據區封裝為一個結構體
(1)因為鏈表實際解決的問題是多種多樣的,所以內部數據區域的結構體構成也是多種多樣的。
- 這樣也導致了不同程序當中的鏈表總體構成是多種多樣的。
- 我們無法通過一套泛性的、普遍適用的操作函數來訪問所有的鏈表,意味著我們設計一個鏈表就得寫一套鏈表的操作函數(節點創建、插入、刪除、遍歷……)。
(2)實際上深層次分析會發現
- 不同的鏈表雖然這些方法不能通用需要單獨寫,但是實際上內部的思路和方法是相同的,只是函數的局部地區有不同。
- 實際上鏈表操作是相同的,而涉及到數據區域的操作就有不同
(3)問題
- 能不能有一種辦法把所有鏈表中操作方法里共同的部分提取出來用一套標準方法實現,然后把不同的部分留著讓具體鏈表的實現者自己去處理。
3、內核鏈表的設計思路
(1)內核鏈表中實現一個純鏈表的封裝,以及純鏈表的各種操作函數
- 純鏈表就是沒有數據區域,只有前后向指針;
- 各種操作函數是節點創建、插入、刪除、遍歷。
- 這個純鏈表本身自己沒有任何用處,它的用法是給我們具體鏈表作為核心來調用。
4、list.h文件簡介
(1)內核中核心純鏈表的實現在include/linux/list.h文件中
(2)list.h中就是一個純鏈表的完整封裝,包含節點定義和各種鏈表操作方法。
二、內核鏈表的基本算法和使用簡介
1、內核鏈表的節點創建、刪除、遍歷等
2、內核鏈表的使用實踐
(1)問題:內核鏈表只有純鏈表,沒有數據區域,怎么使用?
- 使用方法是將內核鏈表作為將來整個數據結構的結構體的一個成員內嵌進去。類似于公司收購,實現被收購公司的功能。
- 這里面要借助container_of宏。
#include <linux/list.h>struct driver_info {int data; };// driver結構體用來管理內核中的驅動 struct driver {char name[20]; // 驅動名稱int id; // 驅動id編號struct driver_info info; // 驅動信息struct list_head head; // 內嵌的內核鏈表成員 };struct driver2 {char name[20]; // 驅動名稱int id; // 驅動id編號struct driver_info info; // 驅動信息//struct list_head head; // 內嵌的內核鏈表成員struct driver *prev;struct driver *next; };// 分析driver結構體,可知:前三個成員都是數據區域成員(就是我們之前簡化為int data的東西),第4個成員是一個struct list_head類型的變量,這就是一個純鏈表。 // 本來driver結構體是沒有鏈表的,也無法用鏈表來管理。但是我們driver內嵌的head成員本身就是一個純鏈表,所以driver通過head成員給自己擴展了鏈表的功能。 // driver通過內嵌的方式擴展鏈表成員,本身不只是有了一個鏈表成員,關鍵是可以通過利用list_head本身事先實現的鏈表的各種操作方法來操作head。// 最終效果:我們可以通過遍歷head來實現driver的遍歷;遍歷head的函數在list.h中已經事先寫好了,所以我們內核中去遍歷driver時就不用重復去寫了。 // 通過操作head來操作driver,實質上就是通過操作結構體的某個成員變量來操作整個結構體變量。這里面要借助container_of宏
總結
- 上一篇: php copy array,ES6中A
- 下一篇: 攻击者利用7号信令(SS7)中的漏洞从德