核心模組程式設計之入門(二) 必備知識

2021-06-19 10:06:20 字數 3293 閱讀 6048

模組程式設計屬於核心程式設計,因此,除了對核心相關知識有所了解外,還需要了解與模組相關的知識。

1.應用程式與核心模組的比較

為了加深對核心模組的了解,表一給出應用程式與核心模組程式的比較。

表一 應用程式與核心模組程式的比較

c語言應用程式 ??? 核心模組程式

使用函式 ??? libc庫 ????????????????? 核心函式

執行空間 ??? 使用者空間 ?? ? ? ? ? ?? 核心空間

執行許可權 ??? 普通使用者 ????????????? 超級使用者

入口函式 ??? main() ????????????????? module_init()

出口函式 ??? exit() ??????????????????? module_exit()

編譯 ?????????? gcc –c ?? ? ? ? ? ? ? ? makefile

連線 ?? ? ? ? ? gcc ????????????????????? insmod

執行 ?????????? 直接執行 ????????????? insmod

除錯 ?????????? gdb ???????????????????? kdbug, kdb,kgdb等

從表一我們可以看出,核心模組程式不能呼叫libc庫中的函式,它執行在核心空間,且只有超級使用者可以對其執行。另外,模組程式必須通過module_init()和module-exit()函式來告訴核心「我來了」和「我走了」。

2.核心符號表(如果對以下第2~4點理解上有困難,可以越過)

如前所述,linux核心是乙個整體結構,像乙個圓球,而模組是插入到核心中的外掛程式。儘管核心不是乙個可安裝模組,但為了方便起見,linux把核心也看作乙個「母」模組。那麼模組與模組之間如何進行互動呢,一種常用的方法就是共享變數和函式。但並不是模組中的每個變數和函式都能被共享,核心只把各個模組中主要的變數和函式放在乙個特定的區段,這些變數和函式就統稱為符號。到低哪些符號可以被共享? linux核心有自己的規定。對於核心這個特殊的母模組,在kernel/ksyms.c中定義了從中可以「移出」的符號,例如程序管理子系統可以「移出」的符號定義如下:

/* 程序管理 */

export_symbol(do_mmap_pgoff);

export_symbol(do_munmap);

export_symbol(do_brk);

export_symbol(exit_mm); …

export_symbol(schedule);

export_symbol(jiffies);

export_symbol(xtime); …

你可能對這些變數和函式已經很熟悉。其中巨集定義export_symbol()本身的含義是「移出符號」。為什麼說是「移出」呢?因為這些符號本來是核心內部的符號,通過這個巨集放在乙個公開的地方,使得裝入到核心中的其他模組可以引用它們。

struct module_symbol ;

我們可以從/proc/ksyms檔案中讀取所有核心模組「移出」的符號,這所有符號就形成核心符號表,其格式如下:

記憶體位址 符號名 [所屬模組]

在模組程式設計中,可以根據符號名從這個檔案中檢索出其對應的位址,然後直接訪問該位址從而獲得核心資料。第三列「所屬模組」指符號所在的模組名,對於從核心這一母模組移出的符號,這一列為空。

模組載入後,2.4核心下可通過 /proc/ksyms、 2.6 核心下可通過/proc/kallsyms檢視模組輸出的核心符號

3.模組依賴

如前所述,核心符號表記錄了所有模組可以訪問的符號及相應的位址。當乙個新的模組被裝入核心後,它所申明的某些符號就會被登記到這個表中,而這些符號可能被其他模組所引用,這就引出了模組依賴這個問題。

乙個模組a引用另乙個模組b所移出的符號,我們就說模組b被模組a引用,或者說模組a依賴模組b。如果要鏈結模組a,必須先鏈結模組b。這種模組間相互依賴的關係就叫模組依賴。

4.模組引用計數器

為了確保模組安全地解除安裝,每個模組都有乙個引用計數器。當執行模組所涉及的操作時就遞增計數器,在操作結束時就遞減這個計數器;另外,當模組b被模組a引用時,模組b的引用計數就遞增,引用結束,計數器遞減。什麼時候可以解除安裝這個模組?當然只有這個計數器值為0的時候,例如,當乙個檔案系統還被安裝在系統上時就不能將其解除安裝,當這個檔案系統不再被使用時,引用計數器就為0,於是可以解除安裝。

四.模組編譯

linux 中最重要的軟體開發工具是 gcc。gcc 是 gnu 的 c 和 c++ 編譯器。但是,在大型的開發專案中,通常有幾十到上百個的原始檔,如果每次均手工鍵入 gcc 命令進行編譯的話,則會非常不方便。因此,人們通常利用 make 工具來自動完成編譯工作。利用這種自動編譯可大大簡化開發工作,避免不必要的重新編譯。這些工作包括:如果僅修改了某幾個原始檔,則只重新編譯這幾個原始檔;如果某個標頭檔案被修改了,則重新編譯所有包含該標頭檔案的原始檔。

1.編譯工具make

實際上,make 工具通過乙個稱為 makefile 的檔案來完成並自動維護編譯工作。makefile 需要按照某種語法進行編寫,其中說明了如何編譯各個原始檔並連線生成可執行檔案,並定義了原始檔之間的依賴關係。下面給出2.6 核心模組的makefile模板(請參看makefile的寫法)

# makefile2.6

obj-m += hellomod.o??????? # 產生hellomod 模組的目標檔案

current_path := $(shell pwd)?? #模組所在的當前路徑

linux_kernel := $(shell uname -r)??? #linux核心源**的當前版本

linux_kernel_path := /usr/src/linux-headers-$(linux_kernel) #linux核心源**的絕對路徑

all:

make -c $(linux_kernel_path) m=$(current_path) modules?? #編譯模組了

clean:

make -c $(linux_kernel_path) m=$(current_path) clean??? #清理

注意: 在每個命令前(例如make命令前)要鍵入乙個製表符(按tab鍵產生)

有了makefile,執行make命令,會自動形成相關的字尾為.o和.ko檔案。

到此,模組編譯好了,該把它插入到核心了:

如:$insmod hellomod.ko

當然,要以系統員的身份才能把模組插入。

成功插入後,可以通過dmesg命令檢視,螢幕最後幾行的輸出就是你程式中輸出的內容:hello,world! from the kernel space…

當模組不再需要時,可以通過rmmod命令移去,例如

$rmmod hellomod

核心模組程式設計之入門(二) 必備知識

模組程式設計屬於核心程式設計,因此,除了對核心相關知識有所了解外,還需要了解與模組相關的知識。1 應用程式與核心模組的比較 為了加深對核心模組的了解,表一給出應用程式與核心模組程式的比較。表一 應用程式與核心模組程式的比較 c語言應用程式 核心模組程式 使用函式 libc庫 核心函式 執行空間 使用...

核心模組程式設計入門之二

模組程式設計屬於核心程式設計,因此,除了對核心相關知識有所了解外,還需要了解與模組相關的知識。1 應用程式與核心模組的比較 為了加深對核心模組的了解,表一給出應用程式與核心模組程式的比較。表一 應用程式與核心模組程式的比較 c語言應用程式 核心模組程式 使用函式 libc庫 核心函式 執行空間 使用...

核心模組程式設計入門總結 1

1.出現編譯的模組不符合當前模組的問題 原因 基本都是因為在用gcc編譯的時候加入了 i引數指定原始碼樹,但是所指定的版本和當前的核心版本衝突的問題。比如我碰到的是2.4.20 8custom rh9.0自帶的核心 的問題,和我們後來編譯的2.4.20 8的衝突。解決 修正.include linu...