linux編寫驅動模組入門
1、linux裝置驅動簡介
以 LInux 的方式看待裝置可區分為 3 種基本裝置型別. 每個模組常常實現 3 種類型中的 1 種, 因此可分類成字元模組, 塊模組, 或者一個網路模組.
2、hello world驅動
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void)
{
printk(KERN_ALERT "Hello, world\n");
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT "Goodbye, cruel world\n");
}
module_init(hello_init);
module_exit(hello_exit);
解釋:這個模組定義了兩個函式, 一個在模組載入到核心時被呼叫( hello_init )以及一個在模組被去除時被調
用( hello_exit). moudle_init 和 module_exit 這幾行使用了特別的核心巨集來指出這兩個函式的
角色. 另一個特別的巨集 (MODULE_LICENSE) 是用來告知核心, 該模組帶有一個自由的許可證; 沒有這樣
的說明, 在模組載入時核心會抱怨.printk 函式在 Linux 核心中定義並且對模組可用; 它與標準 C 庫
函式 printf 的行為相似. 核心需要它自己的列印函式, 因為它靠自己執行, 沒有 C 庫的幫助. 模組能
夠呼叫 printk 是因為, 在 insmod 載入
數和變數, 下一節詳述). 字串KERN_ALERT 是訊息的優先順序你可以用 insmod 和 rmmod 工具來測試
這個模組. 注意只有超級用戶可以載入和解除安裝模組,modprobe 工具值得快速提及一下. modprobe, 如
同 insmod, 載入一個模組到核心. 它的不同在於它會檢視要載入的模組, 看是否它引用了當前核心沒有定
義的符號. 如果發現有, modprobe 在定義相關符號的當前模組搜尋路徑中尋找其他模組. 當 modprobe
找到這些模組( 要載入模組需要的 ), 它也把它們載入到核心. 如果你在這種情況下代替以使用 insmod ,
命令會失敗, 在系統日誌檔案中留下一條 " unresolved symbols "訊息.。
3、Makefile的編寫
# If KERNELRELEASE is defined, we've been invoked from the
# kernel build system and can use its language.
ifneq ($(KERNELRELEASE),)
obj-m := hello.o
# Otherwise we were called directly from the command
# line; invoke the kernel build system.
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
endif
4、核心符號表的匯出
EXPORT_SYMBOL(name);
EXPORT_SYMBOL_GPL(name);
5、模組引數
這些引數的值可由 insmod 或者 modprobe 在載入時指定; 後者也可以從它的配置檔案(/etc/modprobe.conf)
讀取引數的值. 這些命令在命令列裡接受幾類規格的值. 作為演示這種能力的一種方法, 想象一個特別需要的對本章開始的"hello world"模組(稱為 hellop)的改進. 我們增加 2 個引數:一個整型值, 稱為 howmany, 一個字串稱為
whom. 我們的特別多功能的模塊就在載入時, 歡迎whom 不止一次, 而是 howmany 次. 這樣一個模組可以用這樣的命
令行載入:insmod hellop howmany=10 whom="Mom"
一旦以那樣的方式載入, hellop 會說 "hello, Mom" 10 次.但是, 在 insmod 可以修改模組引數前, 模組必須使
它們可用. 引數用 moudle_param 巨集定義來宣告,它定義在 moduleparam.h. module_param 使用了 3 個引數:
變數名, 它的型別, 以及一個許可權掩碼用來做一個輔助的 sysfs 入口. 這個巨集定義應當放在任何函式之外, 典型地是出
現在原始檔的前面. 因此 hellop 將宣告它的引數, 並如下使得對 insmod 可用:
static char *whom = "world";
static int howmany = 1;
module_param(howmany, int, S_IRUGO);
module_param(whom, charp, S_IRUGO);
模組引數支援許多型別:
bool
invbool
int
long
short
uint
ulong
ushort