linux核心init系列函式

2021-07-22 02:45:18 字數 2507 閱讀 3202

核心中每個字元裝置都對應乙個 cdev 結構的變數,下面是它的定義:

linux-2.6.22/include/linux/cdev.h

struct cdev ;

乙個 cdev 一般它有兩種定義初始化方式:靜態的和動態的。

靜態記憶體定義初始化:

struct cdev my_cdev;

cdev_init(&my_cdev, &fops);

my_cdev.owner = this_module;

動態記憶體定義初始化:

struct cdev *my_cdev = cdev_alloc();

my_cdev->ops = &fops;

my_cdev->owner = this_module;

兩種使用方式的功能是一樣的,只是使用的記憶體區不一樣,一般視實際的資料結構需求而定。

下面貼出了兩個函式的**,以具體看一下它們之間的差異。

struct cdev *cdev_alloc(void)

return p;

}void cdev_init(struct cdev *cdev, const struct file_operations *fops)

由此可見,兩個函式完成都功能基本一致,只是 cdev_init() 還多賦了乙個 cdev->ops 的值。

初始化 cdev 後,需要把它新增到系統中去。為此可以呼叫 cdev_add() 函式。傳入 cdev 結構的指標,起始裝置編號,以及裝置編號範圍。

int cdev_add(struct cdev *p, dev_t dev, unsigned count)

核心中所有都字元裝置都會記錄在乙個 kobj_map 結構的 cdev_map 變數中。這個結構的變數中包含乙個雜湊表用來快速訪問所有的物件。kobj_map() 函式就是用來把字元裝置編號和 cdev 結構變數一起儲存到 cdev_map 這個雜湊表裡。當後續要開啟乙個字元裝置檔案時,通過呼叫 kobj_lookup() 函式,根據裝置編號就可以找到 cdev 結構變數,從而取出其中的 ops 字段。

kobj_map函式中雜湊表的實現原理和前面註冊分配裝置號中的幾乎完全一樣,通過要加入系統的裝置的主裝置號major(major=major(dev))來獲得probes陣列的索引值i(i = major % 255),然後把乙個型別為struct probe的節點物件加入到probes[i]所管理的鍊錶中,如圖2-6所示。其中struct probe所在的矩形塊中的深色部分是我們重點關注的內容,記錄了當前正在加入系統的字元裝置物件的有關資訊。其中,dev是它的裝置號,range是從次裝置號開始連續的裝置數量,data是一void *變數,指向當前正要加入系統的裝置物件指標p。圖2-6展示了兩個滿足主裝置號major % 255 = 2的字元裝置通過呼叫cdev_add之後,cdev_map所展現出來的資料結構狀態。

圖2-6  通過cdev_add向系統中加入裝置

所以,簡單地說,裝置驅動程式通過呼叫cdev_add把它所管理的裝置物件的指標嵌入到乙個型別為struct probe的節點之中,然後再把該節點加入到cdev_map所實現的雜湊鍊錶中。

對系統而言,當裝置驅動程式成功呼叫了cdev_add之後,就意味著乙個字元裝置物件已經加入到了系統,在需要的時候,系統就可以找到它。對使用者態的程式而言,cdev_add呼叫之後,就已經可以通過檔案系統的介面呼叫到我們的驅動程式。

當乙個字元裝置驅動不再需要的時候(比如模組解除安裝),就可以用 cdev_del() 函式來釋放 cdev 占用的記憶體。

void cdev_del(struct cdev *p)

其中 cdev_unmap() 呼叫 kobj_unmap() 來釋放 cdev_map 雜湊表中的物件。kobject_put() 釋放 cdev 結構本身。

靜態記憶體與動態記憶體之間的區別

1. 靜態記憶體

靜態記憶體是指在程式開始執行時由編譯器分配的記憶體,它的分配是在程式開始編譯時完成的,不占用cpu資源。

程式中的各種變數,在編譯時系統已經為其分配了所需的記憶體空間,當該變數在作用域內使用完畢時,系統會

自動釋放所占用的記憶體空間。

變數的分配與釋放,都無須程式設計師自行考慮。

eg:基本型別,陣列

2. 動態記憶體

使用者無法確定空間大小,或者空間太大,棧上無法分配時,會採用動態記憶體分配。

3. 區別

a) 靜態記憶體分配在編譯時完成,不占用cpu資源; 動態記憶體分配在執行時,分配與釋放都占用cpu資源。

b) 靜態內存在棧(stack)上分配; 動態記憶體在堆(heap)上分配。

c) 動態記憶體分配需要指標和引用型別支援,靜態不需要。

d) 靜態記憶體分配是按計畫分配,由編譯器負責; 動態記憶體分配是按需分配,由程式設計師負責。

linux核心cdev init系列函式

核心中每個字元裝置都對應乙個 cdev 結構的變數,下面是它的定義 linux 2.6.22 include linux cdev.h 基本相同 struct cdev 乙個 cdev 一般它有兩種定義初始化方式 靜態的和動態的。靜態記憶體定義初始化 struct cdev my cdev cdev...

核心函式系列

如果我們了解系統呼叫表有關知識,也已知道如何攔截系統呼叫表中的函式,那麼下面,我們再來了解一下我們要鉤取的函式 目標函式。這方面,如果我們不僅了解系統呼叫表中有哪些函式,還知道這些函式的工作機制就最好了。但實際上,ntdll.dll 中的匯出函式有好幾百個,別說乙個乙個的 就是把它們都列出來,看著看...

main 函式和 init 函式

go裡面有兩個保留的函式 init函式 能夠應用於所有的package 和main函式 只能應用於package main 這兩個函式在定義時不能有任何的引數和返回值。雖然乙個package裡面可以寫任意多個init函式,但這無論是對於可讀性還是以後的可維護性來說,我們都強烈建議使用者在乙個pack...