一個最簡單的Linux驅動程序的編譯運行
一、背景知識
可裝載內核模塊:為了使系統功能能夠更靈活的擴充,Linux支持內核的動態擴展,即在系統運行時給內核增加新的功能(即模塊module)。
模塊:模塊(module)是一段可以被動態鏈接的目標代碼(.ko),它可由insmod命令動態的裝載并鏈接到正在運行的內核。鏈接后,它就成了內核的一部分,直到用rmmod命令解除鏈接并卸載。
Linux驅動程序就是一種特殊的可裝載內核模塊。
說明:本代碼在linux2.6以上測試運行通過。linux3.*也可。本人用ubuntu12.04,linux內核版本linux3.5。
二、編譯內核模塊
如何由源碼(.c文件)生成動態鏈接的目標代碼(即.ko文件)?
首先寫一個最簡單的驅動程序源碼:hello.c
[html] view plain copy
- #include <linux/init.h> //聲明頭文件
- #include <linux/module.h>
- //模塊加載函數
- static int hello_init(void)
- {
- printk(KERN_INFO " Hello World enter\n"); //系統調用打印函數,類似于用戶調用的printf
- return 0;
- }
- //模塊卸載函數
- static void hello_exit(void)
- {
- printk(KERN_INFO " Hello World exit\n ");
- }
- module_init(hello_init); //向系統注冊模塊加載函數
- module_exit(hello_exit); //向系統注冊模塊卸載函數
- MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); //模塊作者等信息聲明,可選
- MODULE_LICENSE("Dual BSD/GPL"); //模塊許可證聲明
- MODULE_DESCRIPTION("A simple Hello World Module"); //模塊描述聲明,可選
- MODULE_ALIAS("a simplest module"); //模塊別名的聲明,可選
將這段程序編譯為hello.ko的步驟:
1、編寫makefile文件
[html] view plain copy
- KVERS = $(shell uname -r) #變量KVERS為當前linux版本值
- obj-m += hello.o
- default:
- make -C /lib/modules/$(KVERS)/build M=$(CURDIR) modules
-C后面是linux內核源碼樹目錄,M=后面是源碼目錄
2、在終端下輸入 cd /**/**,找到hello.c源碼所在的目錄
3、在終端輸入 make命令。
4、如圖所示即可生成hello.ko文件。
其他文件是生成的一些中間文件。
三、裝載
加載:在終端輸入insmod命令,模塊加載完成。
注意:如果終端沒有打印printk語句,在linux系統日志文件/var/log/syslog中查看。
卸載:在終端輸入remmod命令。
打印信息同在日志文件中。
四、一些理論知識
模塊加載函數:用宏“module_init”指定,它返回整型值。若初始化成功則返回0,若失敗則返回一個負值作為錯誤碼。
模塊卸載函數必須用宏“module_exit”指定,無返回值。
printk用法:
1、printk(KERN_INFO "Hello, world!/n");
2、printk("<6>Hello, world!/n");
***個參數指定輸出級別:分為以下八種:
1、KERN_EMERG 用于緊急消息, 常常是那些崩潰前的消息.
2、KERN_ALERT 需要立刻動作的情形.
3、KERN_CRIT 嚴重情況, 常常與嚴重的硬件或者軟件失效有關.
4、KERN_ERR 用來報告錯誤情況; 設備驅動常常使用 KERN_ERR 來報告硬件故障.
5、KERN_WARNING 有問題的情況的警告, 這些情況自己不會引起系統的嚴重問題.
6、KERN_NOTICE 正常情況, 但是仍然值得注意. 在這個級別一些安全相關的情況會報告.
7、KERN_INFO 信息型消息. 在這個級別, 很多驅動在啟動時打印它們發現的硬件的信息.
8、KERN_DEBUG 用作調試消息.