1. 程式人生 > >linux編寫驅動模組入門

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