Linux核心分析與應用 學習筆記(一)

2021-10-05 23:02:16 字數 3926 閱讀 6982

#include

#include

#include

/* * 模組的初始化函式

* __init 為作用於初始化的修飾符

* /static int __init lkp_init(void)

/* * 模組的退出函式

* __exit為作用於退出的修飾符

* /static void __exit lkp_exit(void)

module_init(lkp_init);

module_exit(lkp_exit);

/* * 模組的許可證宣告gpl

*/module_license

("gpl"

);

obj-m:=hello.o

current_path:=

$(shell pwd

)linux_kernel:=

$(shell uname -r)

linux_kernel_path:=/usr/src/linux-headers-$(linux_kernel)

all:

make -c $(linux_kernel_path)

m=$(current_path)

modules

clean:

make -c $(linux_kernel_path)

m=$(current_path)

clean

// 雙鏈表的定義

struct list_head

;

hash表的資料結構

核心位置/include/linux/types.h

1.那麼為什麼雜湊表中頭節點hlist_head與其他節點hlist_node不同,而沒有採用相同的結構體呢?

由於雜湊表中一般採用單雜湊的形式,並不需要雙鏈表的雙向迴圈功能,所以linux核心為了減少開銷,並沒有用hlist_node來指定雜湊表頭結點,而是採用了hlist_head結構,以減少儲存空間的占用。頭結點的數量與資料的總量在同乙個數量級。

2.為什麼在hlist_node中prev採用了二級指標,而沒有採用單鏈表,或雙向鍊錶的形式呢?

(1)若使用單鏈表結構,在插入節點的時候可以採用在雜湊表的頭結點之後插入節點,此時時間複雜度為o(1)。但在刪除節點的時候必須要遍歷鍊錶來尋找待刪除節點的前乙個節點,此時效率較低。

(2)若prev採用一級指標,則鍊錶的形式如下:

再繼續插入節點node2,node3,node4的時候,插入的方式:

頭插法:

my_list.first = node[x]

;node[x]

->pprev =

(struct hlist_node*

)&my_hlist;

node[x]

->next = node[x-1]

;

尾插法:

node[x]

->next = node[x-1]

->next;

node[x]

->pprev = node[x-1]

;

(

struct hlist_head*

)node1->pprev->first = node1->next;

node1->next->pprev =

(struct hlist_node*

)&my_hlist / node1->pprev;

當刪除node2~4其他節點時,

node[x]

->pprev->next = node[x]

->next;

node[x]

->next->pprev = node[x]

->pprev;

從節點的插入與刪除中,我們可以看到若pprev採用一級指標,則第乙個節點的插入與刪除操作與其他節點的操作方式是不一樣的,同時還需要進行hlist_dead和hlist_node之間的型別強制轉換。因此linux核心中為了統一節點的插入與刪除操作方式,將pprev指標設定為了二級指標。

linux核心中將pprev指標設計為二級指標有如下好處

為了間接改變表頭中hlist_node型別first指標的值,使用了二級指標,因此在node節點中pprev中儲存的為前乙個結點中第乙個元素的位址,頭結點中即為first指標,其餘節點則為next。

//初始化時,first指標指向null

mylist->first = node1;

node2->pprev =

&(my_list->first)

;node2->next = my_list->first;

// 或node1,為了與插入第乙個節點的操作保持一致

my_list->first = node2;

尾插法

node2->pprev =

&(node1->next)

;node2->next = node1->next;

node1->next = node2;

這樣一來所有節點的刪除和插入操作方式都是完全一樣的。

雜湊表中的巨集定義

//初始化頭結點

#define hlist_head_init

//宣告並初始化頭結點

#define hlist_head(name) struct hlist_head name =

//初始化頭結點

#define init_hlist_head(ptr) ((ptr)->first = null)

//初始化其他節點

#define init_hlist_node(ptr) ((ptr)->next = null, (ptr)->pprev = null)

核心中的雜湊表結構

Linux核心分析 Linux核心學習總結

這學期選了孟老師的 linux核心分析 這門課,在學習之前聽說這門課很難,通過也不是很容易,但我還是選了這門課。課程不容易學,含金量才會大,才會有收穫。現在,學習這門課已經兩個月了,我的收穫很大,特別是以前接觸 計算機組成原理 作業系統 這兩門課時遇到的很難理解的地方,通過孟老師的linux核心講解...

linux核心分析學習總結

實驗目錄 實驗1 反彙編 c 語言程式 小結 序的堆疊呼叫大體過程是堆疊先向下增加,然後再向上還原的乙個過程,整個程式通過指令線性流過 cpu。不足 流程圖還可以再畫好一些。實驗2 乙個簡單的時間片輪轉多道程式分析 小結 可以看出計算機所謂的多工處理也只是週期性的產生中斷來輪流招待不同的程式,cpu...

《Spark核心原始碼分析與開發實戰》讀書筆記之一

第1章 spark系統概述 1.1 spark是什麼 1.spark比hadoop快在 1 spark使用記憶體計算,而hadoop使用io 2 hadoop的計算是按部就班一步一步進行的,而spark則是提前生成了dag,優化了運算路徑 1.2 spark生態系統bdas 1.bdas 伯克利資料...