linux核心筆記(一)

2021-10-08 17:07:13 字數 3946 閱讀 6482

需要了解知識:

linux

c語言makefile

linux是單核心(或單核心)的操作體系統。(windows微核心)

單核心是所有的核心功能被整體編譯在一起,形成乙個單獨的核心映象,核心中各模組的互動是通過直接的函式呼叫,效率非常高。

微核心是實現核心中相當關鍵和核心的一部分,其他功能模組被單獨編譯,功能模組之間的互動通過微核心提供的某種通訊機制來建立的。

單核心如果要增加、刪除、修改核心的某個功能,就不得不重新編譯整個核心,為了解決這一問題,引入了核心模組。核心模組是被單獨編譯的一段核心**,它可以在需要的時候動態載入到核心,不需要時,動態解除安裝(需要核心配置了可解除安裝的選項),不需要重啟整個系統,這種特性非常適合驅動程式開發。

#include#include#includeint init_module(void)

void cleanup_module(void)

核心原始碼樹中的標頭檔案。包含了init_module和cleanup_module兩個函式原型宣告

包含了printk函式的原型宣告

暫時沒用

乙個模組程式幾乎都要直接或間接包含上述三個模組。

init_module函式時模組的初始化函式(非必要),不接受引數,成功返回0;失敗返回乙個負數。

printk函式類似於printf,但支援額外的列印級別,用於除錯目的。

cleanup_module函式是模組的清除函式(非必要),在模組從核心中解除安裝時呼叫。但要是提供了模組初始化函式,則清除函式是要提供的(除非核心模組不允許解除安裝)。

makefile

簡單的做法是把剛才的**新增到核心原始碼樹中,然後修改對應的makefile檔案即可,但這回修改核心的原始碼;另一種是將c檔案放到核心原始碼樹外乙個單獨的目錄中,然後在該目錄下編寫乙個對應的makefile。

ifeq($(kernelrelease),)

ifeq($(arch),arm)

kerneldir?=/home/farsight/fs4412/linux-3.14.25-fs4412

rootfs?=/nfs/rootfs

else

kerneldir?=/lib/moudle/$(shell uname -r)/build

endif

pwd:=$(shell pwd)

module:

$(make) -c $(kerneldir)m=$(pwd)modules

modules_install:

$(make) -c $(kerneldir)m=$(pwd)install_mod_path=$(rootfs)modules_install

clean:

rm -rf *.0 *.ko *.cmd *.mod modules.order module.symvers.tmp_versions

else

obj-m:=vser.o

endif

略 

模組載入

insmod:載入指定目錄下的乙個.ko檔案到核心

模組載入成功後使用dmesg命令可以看到控制台輸出資訊

modprobe:自動載入模組島內和,相比insmod更智慧型,推薦使用。但莫要要執行安裝操作,在執行該命令前最好執行一次depmod命令來更新模組的依賴資訊。modeprobe不指定路徑及字尾

模組資訊

modinfo:檢視模組資訊,在安裝了模組並執行depmod命令後,可以不指定路徑和字尾,也可以指定檢視某一特定的.ko檔案的資訊

模組解除安裝

rmod:如果核心配置允許解除安裝模組,那麼rmmod將指定的模組從核心中解除安裝。

gpl許可協議略。在**中需要新增**表示改**接收響應的許可協議。

module_license("gpl");
moudle_license是乙個巨集,裡面的引數是乙個字串,代表相應的許可證協議。可以是gpl,gpl v2,gpl and additional rights等。這個巨集將會生成一些模組資訊,放在elf檔案中的乙個特殊的段中,模組在載入時會將該資訊複製到記憶體中,並檢查該資訊。不加這段**。會導致核心報警告或關閉某些除錯功能,某些功能函式是不能呼叫的,開發驅動呼叫核心的一些基礎設施(一些核心的api函式)是必不可少的。

模組的初始化函式和清楚函式的名字是固定的,入口函式基本都為main。核心借助於gun的函式別名機制,可以靈活的指定模組的初始化函式和清楚函式的別名。

module_init(vser_init);

module_exit(vser_exit);

module_init和module_exit是兩個巨集,分別用於指定init_module和函式別名vser_init和cleanup_exit的別名是vser_exit。

為了避免因為重名帶來重讀定義的問題,函式可以加static關鍵字修飾,經過static修飾後的函式的鏈結屬性為內部。這也是幾乎所有驅動程式的函式前都要加static關鍵字修飾的原因。

linux是節約記憶體的作業系統。上面的初始化函式僅會被呼叫1次,之後就可以釋放掉這函式占用的記憶體,在函式名前加__init可以達到此目的。__init是把這些標記的函式放到elf檔案的特定**段,在模組載入這些段時將會單獨分配記憶體,這些函式呼叫成功後,模組的引導程式會釋放這部分記憶體。__exit用於修飾清除函式,類似於__init,如果模組不允許且在,那麼這段**完全就不用載入。

#include#include#includestatic int __init vser_init(void)

static void __exit vser_exit(void)

module_init(vser_init);

module_exit(vser_exit);

module_license("gpl");

module_author("***");

module_description("******");

module_alias("virtual-serial");

對於乙個較複雜的驅動程式,將所有**寫在乙個原始檔不太現實,通常會把程式功能拆分,由不同的原始檔來實現對應的功能。

使用make,將多個目標檔案共同生成的。

模組的初始化函式在模組被載入時呼叫,但該函式不接受引數。模組提供了另外一種形式來支援引數傳遞資訊,叫做模組引數。

模組引數允許使用者在載入模組時通過命令列指定引數,並轉換成相應型別的值,然後賦值給對應的辯論,這個過程發生在呼叫模組初始化函式之前。核心支援的引數型別有:bool,inbool(反轉值bool)、charp(字串指標)、short、int、long、ushort、uint、ulong這些型別又可以復合成對應的陣列型別。

module_param(name,type,perm)

module_param_array(name,type,nump,perm)

name:變數的名字

type:變數或陣列元素的型別

nump:陣列元素個數的指標(可選)

perm:在sysfs檔案系統中對應檔案的許可權屬性,如果為0,則sysfs檔案系統中不會出現任何對應檔案。

雖然**中增加模組引數的寫許可權可以通過sysfs檔案系統來修改模組引數的值,但不推薦。因為這種方式對模組引數驚醒的修改模組本身是一無所知。

使用file命令和nm命令可以得到elf目標檔案的相關細節資訊

如果要使用insmod命令載入模組,則必須線載入dep模組再載入vser模組。

兩個模組存在依賴關係,如果分別編譯,會出現警告資訊,即使載入順序正確,載入也不會成功

解除安裝模組要先解除安裝vser模組在寫在dep模組。核心會建立模組依賴關係的鍊錶,只有當依賴於這個模組的鍊錶為空時,模組才能被解除安裝。

linux核心是由全世界的志願者開發的,不同版本函式介面可能完全不一樣。

核心模組和普通應用程式的差異:

Linux核心 驅動學習筆記 一

今天討論到核心啟動階段對外部裝置初始化的過程,於是粗略的看了一下相關 得到以下一些印象 未必正確,希望大家指正 1.對外部裝置初始化 出現的地方應該是 init 程序 bootloader start 彙編 decompress start kernel rest init kernel threa...

LINUX核心程式設計 學習筆記(一)

linux核心使用bitmap相關 1,宣告乙個bitmap陣列,可以表示100個bit,陣列名字是bitmap declare bitmap bitmap,100 define declare bitmap name,bits unsigned long name bits to longs bi...

Linux核心學習筆記一

核心與作業系統 核心是作業系統的核心部分,包含了系統執行的核心過程,決定系統的效能,作業系統啟動核心被裝入到ram中 作業系統與底層硬體裝置互動和為執行應用程式提供執行環境。linux核心與微核心比較 微核心 核心只需要乙個很小的函式集,通常包括幾個同步原語,乙個簡單的排程程式和程序間通訊機制。執行...