內核模塊開發 初步

LINUX內核模塊基礎

什麼是內核模塊:
Linux內核的整體結構非常龐大,其包含的組件也非常多,如何使用這些組件呢,有一種方法是:把所有的組件都編譯進內核文件,即:zImage或bzImage,但這樣會導致一個問題:佔用內存過多。
應當採用一種機制能讓內核文件本身並不包含某組件,而是在該組件需要被使用的時候,動態地添加到正在運行的內核中。

內核模塊具有如下特點:
• 模塊本身並不被編譯進內核文件(zImage或者bzImage)。
• 可以根據需求,在內核運行期間動態的安裝或卸載。

安裝與卸載內核模塊:
安裝 insmod
例:insmod /home/dnw_usb.ko

卸載 rmmod
例:rmmod dnw_usb

查看 lsmod
例:lsmod

內核模塊設計

內核模塊C程序代碼舉例:

//Linux內核模塊的三要素:頭文件、加載函數、卸載函數
#include <linux/init.h>
#include <linux/module.h>

//加載和卸載函數都要加上static靜態函數
//在內核中打印不能使用 printf ,要使用 printk 函數
static int hello_init()
{
    printk(KERN_WARNING"Hello world!\n");//沒有逗號,KERN_WARNING 是優先級
    return 0;   
}

static void hello_exit()
{
    printk(KERN_WARNING"hello exit!\n");    
}

module_init(hello_init); //加載函數,insmod命令之後自動開始執行括號內的函數
module_exit(hello_exit); //卸載函數,rmmod命令之後自動開始執行括號內的函數

makefile文件編寫:

obj-m := helloworld.o
#helloworld.o是最終生成的內核模塊的名字,上面是單個文件的寫法
#多個文件的寫法:
#obj-m := hello.o
#hello-objs := file1.o file2.o file3.o

KDIR := /home/ARM_Linux/system2/season4/First/part3/linux-ok6410 
#開發板上運行的內核代碼的路徑,編譯內核需要依賴於內核路徑,注意斜線方向

all:
    make -C $(KDIR) M=$(PWD) modules CROSS_COMPILE=arm-linux- ARCH=arm
    # -C 表示進入後面的路徑中,因此還需要加上內核模塊代碼的路徑
    # pwd 是內核模塊代碼的路徑
clean:
    rm -f *.o *.ko *.order *.symvers *.bak *.mod.c

對代碼進行編譯,可以得到 .ko 文件,將 .ko 文件拷貝到嵌入式系統的根文件系統中。

在嵌入式系統上,用insmod命令加載模塊和用rmmod命令寫在模塊,都可以看到程序的運行效果。

內核模塊可選信息

該部分是模塊中可選的信息,可有也可以沒有。

模塊申明:
加入下面的宏,聲明相應的信息:

1、MODULE_LICENSE(“遵守的協議”);
申明該模塊遵守的許可證協議,如:GPL、GPL v2等

2、MODULE_AUTHOR(“作者”);
申明模塊的作者

3、MODULE_DESCRIPTION(“模塊的功能描述”);
申明模塊的功能

4、MODULE_VERSION(“V1.0”);
申明模塊的版本

模塊參數:
在應用程序中:

int main(int argc, char** argv)

argc表示命令行輸入的參數個數,argv中保存輸入的參數。

內核模塊中可以通過命令行輸入參數,例如:

insmod xx.ko 某個變量=某個值(該變量必須在程序中用宏指定)

但是,必須先通過宏module_param指定保存模塊參數的變量。模塊參數用於在加載模塊時傳遞參數給模塊。

module_param(name, type, perm);

name:變量的名稱
type:變量類型,bool:布爾型,int:整型,charp:字符串型。
perm:是訪問權限。 S_ IRUGO:讀權限,S_IWUSR:寫權限。

例程,傳入兩個參數:

int a = 3;
char *st;
module_param(a,int, S_IRUGO|S_IWUSR);
module_param(st,charp, S_IRUGO|S_IWUSR);


insmod xx.ko a=xx st=xx

符號導出:
一個模塊的數據給其他模塊使用必須要進行符號導出。

內核符號的導出使用宏

EXPORT_SYMBOL(符號名);
EXPORT_SYMBOL_GPL(符號名);
//符號名可以是變量,可以是函數名
//調用該符號的文件要使用extern聲明該符號
//同時還要注意不同內核的安裝順序

說明:
其中EXPORT_ SYMBOL_GPL只能用於包含GPL許可證的模塊。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章