嵌入式設備驅動開發中將驅動程序以模塊的形式發布,更是極大地提高了設備使用的靈活性——用戶只需要拿到相關驅動模塊,再插入到用戶的內核中,即可靈活地使用你的設備。 1.1.2 使用Linux模塊的優點 1. 用戶可以隨時擴展Linux系統的功能。 2. 當要修改當前Linux系統的驅動時,只需要卸載舊模塊,編譯目標驅動模塊,重新安裝插入即可。 3. 系統中如果需要使用新模塊,不必重新編譯內核,只要插入相應的模塊即可。 4. 減小Linux內核的體積,節省flash。 1.2 Linux模塊入門
1.2.1 模塊相關命令
1.2.1.1 Linux模塊命令詳細介紹 1. 模塊安裝命令:insmod insmod xxxx.ko 2. 查看當前已經安裝模塊:lsmod lsmod 不需要參數 3. 模塊卸載命令:rmmod rmmod xxxxx.ko 4. 查看模塊信息:modinfo 在X86上操作: [root@zhifachen linux-3.5]# modinfo/root/work/rootfs/home/mod/tiny4412_hello_module.ko filename: /root/work/rootfs/home/mod/tiny4412_hello_module.ko license: GPL depends: intree: Y vermagic: 3.5.0-FriendlyARM SMP preempt mod_unload ARMv7 p2v8 [root@zhifachen linux-3.5]# 1.2.1.2 Linux模塊命令測試示例 注意:模塊的編譯是依賴具體一份源碼,并且這份被編譯過,并且沒有使用mrproper,distclean清除的源碼工程。 1.2.2 使用makemodules編譯內核源碼樹中的模塊 1. 添加內核菜單 2. make menuconfig 配置為 M 3. 在頂層目錄終端輸入makemodules 直接make 也可生成模塊文件(.ko),也會生成zImage,當你只想編譯模塊而不想編譯zImage時候使用 make modules 命令會更加快速。 1.2.3 把內核源碼樹中模塊源文件編譯到內核映像中 如果不需要配置菜單只想編譯代碼到內核zImage,Makefile可以這樣寫obj-y += xxxx.o 如果不需要配置菜單只想編譯代碼為外部模塊,Makefile可以這樣寫 obj-m+= xxxx.o 1.2.4 在內核源碼中添加自定義的模塊并且編譯
1.2.5 外部獨立Makefile編譯模塊 在驅動開發階段,接觸到新驅動機率非常高,如果都要去修改內核源碼Makefile, 太過于繁雜,也不利于移植,實際開發中會使用另外一種方法來編譯模塊文件。 1.2.5.1 Linux內核模塊代碼文件模板 可以直接復制內核源碼中自帶的示例模板來測試:drivers/char/tiny4412_hello_module.c 1.2.5.2 Linux內核模塊編譯Makefile模板 編譯模塊Makefile文件:
obj-m += xyd_hello_module.o all: @make -C /root/work/linux-3.5/ M=$(PWD) modules @rm -rf *.o *.mod.c modules.order Module.symvers *~ *.bak clean: @rm -rf *.o *.mod.c modules.order Module.symvers *.ko *~ *.bak |
make -C $(KDIR)M=$(PWD) modules M=選項讓該Makefile在構造modules目標之前返回到模塊源代碼目錄,然后modules目標指向obj-m變量中設定的模塊;在上面的例子中,我們將該變量設置成了module.o。 上面的清除規則是自己寫的,也可利用內核Makefile清除規則來清編譯生成目標文件,改進后代碼:
obj-m += xyd_hello_module.o # x86 編譯時候使用: uname -r 得到當前內核的版本號 #KDIR := /lib/modules/`uname -r`/build #arm 編譯時候使用 KDIR :=/root/work/linux-3.5
all: @make -C $(KDIR) M=$(PWD) modules
clean: @make -C $(KDIR) M=$(PWD) modules clean @rm -f *.ko.unsigned *~ |
1.1.1 Linux內核printk 函數
內核中不能使用printf函數輸出信息,要使用printk函數,這個函數有輸出等級控制的。 內核通過 printk() 輸出的信息具有日志級別,日志級別是通過在 printk() 輸出的字符串前加一個帶尖括號的整數來控制的,如 printk("<6>Hello, world!/n");。內核中共提供了八種不同的日志級別,在 linux/kernel.h 中有相應的宏對應。 #defineKERN_EMERG "<0>" /* system is unusable 系統不可用*/ #defineKERN_ALERT "<1>" /* action must be takenimmediately警報,必須立即采取行動*/ #define KERN_CRIT "<2>" /*critical conditions臨界狀態 */ #defineKERN_ERR "<3>" /* error conditions 錯誤狀態*/ #defineKERN_WARNING "<4>" /* warningconditions警告狀態*/ #defineKERN_NOTICE "<5>" /* normal but significant正常的,但引人注目*/ #define KERN_INFO "<6>" /*informational 信息*/ #defineKERN_DEBUG "<7>" /* debug-level messages調試等級信息 */ 可以通過 查看/proc/sys/kernel/printk 文件內容知道設置信息。
[root@ChenZhiFa/]# cat /proc/sys/kernel/printk 7 4 1 7
可以通過echo 命令修改種個等級: [root@ChenZhiFa/]# echo 4 4 1 7 > /proc/sys/kernel/printk
說明:直接使用printk( “kkkk”); 這樣沒有指明等級,這種未明確指定。
只有等級比較當前終端等級高才會在終端上顯示出來。 以下進行X86 系統上的測試(在純字符界面下測試有效,在圖形界面中是無效) 在圖形界面系統中按 Ctl + Alt + F2 (F2~F6鍵其中一個,不同電腦可能不同),可以進入到純字符界面,要返回按Ctl +Alt + F1(不同電腦可能不同) printk --- 不支持浮點數,實際上驅動程序也不支持浮點運算。所有浮點運算應該放在用戶空間。
|