一、Linux核心模組基本原理
Linux 核心模組(LKM)是一些在啟動的作業系統核心需要時可以載入核心執行的代碼塊,不需要時由作業系統卸載。它們擴充了作業系統核心功能卻不需要重新編譯核心、啟動系統。如果沒有核心模組,就不得不反覆編譯產生作業系統的核心鏡像來加入新功能,當附加的功能很多時,還會使核心變得臃腫。一個Linux 核心模組主要由以下幾個部分組成:
(1) 模組載入函數(必須):當通過insmod 或modprobe 命令載入核心模組時,模組的載入函數會自動被核心執行,完成本模組相關初始化工作。
(2) 模組卸載函數(必須):當通過rmmod 命令卸載模組時,模組的卸載函數會自動被核心執行,完成與模組載入函數相反的功能。
(3) 模組許可證聲明(必須):模組許可證(LICENCE)聲明描述核心模組的許可許可權,如果不聲明LICENCE,模組被載入時將收到核心被汙染的警告。大多數情況下,核心模組應遵循GPL 相容許可權。Linux2.6 核心模組最常見的是以MODULE_LICENSE(“Dual BSD/GPL”)語句聲明模組採用BSD/GPL 雙LICENSE。
(4) 模組參數(可選):模組參數是模組被載入的時候可以被傳遞給他的值,它本身對應模組內部的全域變數。
(5) 模組匯出符號(可選):核心模組可以匯出符號(symbol,對應於函數或變數),這樣其他模組可以使用本模組中的變數或函數。
(6) 模組作者等資訊聲明(可選)。
一個核心模組至少包含兩個函數,模組被載入時執行的初始化函數init_module()和模組被卸載時執行的結束函數cleanup_module()。在最新核心穩定版本2.6 中,兩個函數可以起任意的名字,通過宏module_init()和module_exit()註冊調用要編譯核心模組,把代碼嵌進核心空間,首先要擷取核心原始碼,且版本必需與當前正在啟動並執行版本一致。 二、編寫helloworld.c及其對應的Makefile。
helloworld.c:
#include <linux/module.h>#include <linux/kernel.h>int init_hello_module(void){ printk("***************Start***************\n"); printk("Hello World! Start of hello world module!\n"); return 0;}void exit_hello_module(void){ printk("***************End***************\n"); printk("Hello World! End of hello world module!\n");}MODULE_LICENSE("Dual BSD/GPL");module_init(init_hello_module);module_exit(exit_hello_module);
Makefile:
# To build modules outside of the kernel tree, we run "make"# in the kernel source tree; the Makefile these then includes this# Makefile once again.# This conditional selects whether we are being included from the# kernel Makefile or not.# called from kernel build system: just declare what our modules areobj-m := helloworld.oCROSS_COMPILE = CC = gcc # Assume the source tree is where the running kernel was built # You should set KERNELDIR in the environment if it's elsewhere KERNELDIR ?= /usr/src/linux-headers-$(shell uname -r) # The current directory is passed to sub-makes as argument PWD := $(shell pwd)all: modulesmodules: $(MAKE) -C $(KERNELDIR) M=$(PWD) modulesclean: rm -rf *.o *~ core .depend *.symvers .*.cmd *.ko *.mod.c .tmp_versions $(TARGET)
在Makefile中,在obj-m := helloworld.o這句中,.o的檔案名稱要與編譯的.c檔案名稱一致。
KERNELDIR ?= /usr/src/linux-headers-$(shell uname -r)指示當前linux系統核心的源碼位置。
三、編譯:
1.在Makefile及helloworld.c所在目錄下,直接make,成功後查看目前的目錄下有無helloworld.ko檔案產生,有則核心模組產生成功。
2.使用insmod命令,把此核心模組程式載入到核心中運行。結合lsmod及管道命令,查看核心模組程式在核心中是否正確運行。
3.查看此核心模組程式列印的資訊,另開一個終端,輸入tail -n /var/log/messages.
使用rmmod命令把之前載入的核心模組卸載掉,然後再次執行第2步,即可看到此核心模組程式列印的資訊。