linux核心模組程式設計的資料有些紛繁複雜,有的過於簡單,有的過於龐雜,我試圖用筆記的形式想讀者展示怎樣來程序linux模組程式設計,力圖做到簡明扼要,這篇文章也是作為本人備忘的資料,所以有些地方過於簡略是難免的。本來這篇文章的目的就是讓使用者知其然,至於所以然還是請參考相應的資料,其實最好的資料莫過於linux kernel source。
適用範圍:
首先這個module不同於microkernel的module,microkernel的module是乙個個的daemon程序,工作於使用者空間,linux的module只是乙個核心的目標**,核心通過執行執行時的連線,來把它整合到kernel中去,所以說linux的module機制並沒有改變linux核心為monolithic os本質,其module也是工作於核心模式,享有核心的所有特權。
至於為什麼要引入linux kernle module(一下簡稱lkm),我想至少有一下幾點:
lkm需要包含以下標頭檔案:
需要定義以下巨集:__kernel__, module
/*file: hello.c*/很簡答吧,不是嗎?這個lkm的功能其實也很簡單,就是當通過insmod載入它的時候,他列印hello, my lkm.通過rmmod解除安裝它的時候他列印bye, my lkm.乙個最基本的核心模組一般都包含有兩個函式,乙個是初始化函式(比如說這裡的hello_init),乙個是解除安裝函式(hello_exit), 當然也可以沒有任何函式,只是提供一些變數。但是初始化函式和解除安裝函式必須成對出現。並且init函式當操作成功時返回值大於等於零,當操作失敗時,返回非零。巨集module_init和module_exit用於註冊初始化函式和解除安裝函式。#ifndef __kernel__
#define __kernel__
#endif
#ifndef module
#define module
#endif
#include
#include
static int __init hello_init(void)
static void __exit hello_exit(void)
module_init(hello_init);
module_exit(hello_exit);
乙個示例的makefile如下所示
obj-m:= hello.o如果這個目錄下面還有其它模組,只需要在hello.o後面新增就行了。kernelbuild:= /lib/modules/`uname -r`/build
default:
make -c $(kernelbuild) m=$(shell pwd) modules
clean:
rm -rf *.o .*.cmd *.ko *.mod.c .tmp_versions
obj-m:= hello.o mod.o在模組所在目錄執行make,等成功後就可以得到我們想要的模組(hello.ko)了。
如果乙個模組存在許多原始檔,比如:hello, 由hello1.c hello2.c共同連線而成,需要在makefile中加入如下行
hello-objs:= hello1.o hello2.olinux為使用者提供了modutils,用來操縱模組。這個工具集主要包括:
insmod 安裝模組試著用命令insmod hello.ko載入模組,rmmod刪除模組,看看有什麼事情發生了。你有可能看不見任何輸出,難道是有錯誤發生?no,執行命令tail /var/log/message呵呵,是不是看到了?rmmod 刪除模組
modprobe 比較高階的載入和刪除模組,可以解決模組之間的依賴性
lsmod 列出已經載入的模組和其資訊
modinfo 用於查詢模組的相關資訊,比如作者,版權...
feb 19 00:07:35 gentux hello, my lkm.feb 19 00:07:38 gentux bye, my lkm.
module_author("author");比較常用的free license有"gpl", "gpl v2", "gpl and additional rights", "dual bsd/gpl", "dual mpl/gpl"。module_description("the description");
module_license("gpl");
module_supported_device("dev"); // 裝置驅動程式所支援的裝置。
module_parm(var, type);模組引數的型別(即module_parm中的type)有一下幾種:module_parm_desc(var, "the description of the var");
這些引數最好有預設值,如果有些必要引數使用者沒有設定可以通過在module_init指定的init函式返回負值來拒絕模組的載入。 lkm還支援陣列型別的模組,如果在型別符號前加上數字n則表示最大程度為n的陣列,用「-」隔開的數字分別代表最小和最大的陣列長度。
示例:如何用insmod傳入引數,其實man一下就可以了,不過現在的man有些過於簡單,所以在此說明一下:module_parm(var, "4i"); // 最大長度為4的整形陣列
module_parm(var, "2-6i"); // 最小長度為2,最大長度為6的整形陣列
insmod variable=value[,value2...] ...其中value可以用引號括起來,也可以不用。但是有一點「=」前後不能留有空格,並且value中也不能有空格。
和使用者空間的應用程式不同的是,引入乙個模組的目的常常是為了給核心提供一些routine,來完成特定的功能,很少有模組什麼符號都不匯出,為此linux為使用者提供了如下巨集:
export_symbol(var); // 輸出symbol var有的時候兩個模組之間可能有依賴性,要載入的模組a,依賴於模組b,此時insmod是無能為力的,只能用modprobe來載入模組和其依賴的模組,否則只能手動乙個個載入。export_symbol_gpl(var); // 輸出的symbol版權為gpl
modprobe通過讀取由depmod -a生成的/lib/modules/version/modules.dep來獲得其所依賴的模組列表(也有可能是乙個模組樹),然後呼叫insmod來乙個個按順序載入。
對於不需要export的全域性symbol最好用static進行修飾,限制其作用域為本檔案,以防汙染核心的命名空間。
對於由核心或其它模組export的一些symbol,最好用extern進行修飾,以示其不在本檔案。
在可能用到errno變數的場合,因為核心沒有export此symbol,只能有使用者自行定義,比如:int errno;
/*file: hello.c*/the linux kernel module programming guide#ifndef __kernel__
#define __kernel__
#endif
#ifndef module
#define module
#endif
#include
#include
module_author("xiaosuo ");
module_license("gpl");
module_description("this module is a example.");
static int int_var = 0;
static const char *str_var = "default";
static int int_array[6];
module_parm(int_var, "i");
module_parm_desc(int_var, "a integer variable");
module_parm(str_var, "s");
module_parm_desc(str_var, "a string variable");
module_parm(int_array, "2-6i");
module_parm_desc(int_array, "a integer array");
static int __init hello_init(void)
return 0;
}static void __exit hello_exit(void)
module_init(hello_init);
module_exit(hello_exit);
linux 核心程式設計指南(第三版)
linux核心分析及程式設計
Linux核心模組程式設計
目標 熟悉linux模組相關函式等 模組載入,例 static int init initialization function void module init initialization function 這裡 init define init attribute section init.t...
linux 2 6 核心模組程式設計探索
乙個linux 核心模組程式設計的手記,未寫完不斷更新中 一 相關命令 0 檢視系統裝載了哪些 核心模組 lsmod modulename 1 載入核心模組 insmod modulename 2 解除安裝核心模組 rmmod modulename 3 建立裝置檔案 mknod filename d...
linux 2 6 核心模組程式設計探索
乙個linux 核心模組程式設計的手記,未寫完不斷更新中 一 相關命令 0 檢視系統裝載了哪些 核心模組 lsmod modulename 1 載入核心模組 insmod modulename 2 解除安裝核心模組 rmmod modulename 3 建立裝置檔案 mknod filename d...