今天將直接了當(dāng)?shù)膸氵M(jìn)入linux的模塊編譯,當(dāng)然在介紹的過程當(dāng)中,我也會(huì)添加一些必要的注釋,以便初學(xué)者能夠看懂。之所以要有這篇文章,主要是因?yàn)閺臅旧蠈W(xué)的話,可能要花更長(zhǎng)的時(shí)間才能學(xué)會(huì)整個(gè)過程,因?yàn)榭磿脑捠且粋€(gè)學(xué)習(xí)過程,而本文更像是一個(gè)培訓(xùn)。所以實(shí)踐性和總結(jié)性更強(qiáng)。讀完本文后你將會(huì)學(xué)到編譯一個(gè)模塊和模塊makefile的基本知識(shí)。以及加載(卸載)模塊,查看系統(tǒng)消息的一些知識(shí)。如果你已經(jīng)是一個(gè)linux模塊編譯高手,您也可以指點(diǎn)指點(diǎn)哪里說的不足。
第一步:準(zhǔn)備源代碼
首先我們還是要來編寫一個(gè)符合linux格式的模塊文件,這樣我們才能開始我們的模塊編譯。假設(shè)我們有一個(gè)源文件mymod.c。它的源碼如下:
mymod.c
1. #include /* 引入與模塊相關(guān)的宏 */
2. #include /* 引入module_init() module_exit()函數(shù) */
3. #include /* 引入module_param() */
4
5. MODULE_AUTHOR("Yu Qiang");
6. MODULE_LICENSE("GPL");
7
8. static int nbr = 10;
9. module_param(nbr, int, S_IRUGO);
10.
11. static int __init yuer_init(void)
12.{
13. int i;
14. for(i=0; i
15. {
16. printk(KERN_ALERT "Hello, How are you. %d ", i);
17. }
18. return 0;
19.}
20.
21.static void __exit yuer_exit(void)
22.{
23. printk(KERN_ALERT"I come from yuer's module, I have been unlad. ");
24.}
25.
26. module_init(yuer_init);
27. module_exit(yuer_exit);
我們的源文件就準(zhǔn)備的差不多了,這就是一個(gè)linux下的模塊的基本結(jié)構(gòu)。第9行是導(dǎo)出我們的符號(hào)變量nbr。這樣在你加載這個(gè)模塊的時(shí)候可以動(dòng)態(tài)修改這個(gè)變量的值。稍后將演示。yuer_init()函數(shù)將在模塊加載的時(shí)候運(yùn)行,通過輸出的結(jié)果可以看到我們的模塊是否加載成功。
第二步:編寫Makefile文件
首先還是來看看我們Makefile的源文件,然后我們?cè)賮斫忉?
Makefile
obj-m := modules.o #要生成的模塊名
modules-objs:= mymod.o #生成這個(gè)模塊名所需要的目標(biāo)文件
KDIR := /lib/modules/`uname -r`/build
PWD := $(shell pwd)
default:
make -C $(KDIR) M=$(PWD) modules
clean:
rm -rf *.o .* .cmd *.ko *.mod.c .tmp_versions
現(xiàn)在我來說明一下這個(gè)Makefile。請(qǐng)記住是大寫的Makefile而不是小寫的makefile;
obj-m :這個(gè)變量是指定你要聲稱哪些模塊模塊的格式為 obj-m := <模塊名>.o
modules-objs :這個(gè)變量是說明聲稱模塊modules需要的目標(biāo)文件 格式要求 <模塊名>-objs := <目標(biāo)文件>
切記:模塊的名字不能取與目標(biāo)文件相同的名字。如在這里模塊名不能取成 mymod;
KDIR :這是我們正在運(yùn)行的操作系統(tǒng)內(nèi)核編譯目錄。也就是編譯模塊需要的環(huán)境
M= :指定我們?cè)次募奈恢?/p>
PWD :這是當(dāng)前工作路徑$(shell )是make的一個(gè)內(nèi)置函數(shù)。用來執(zhí)行shell命令。
第三步:編譯模塊
現(xiàn)在我們已經(jīng)準(zhǔn)備好了我們所需要的源文件和相應(yīng)的Makefile。我們現(xiàn)在就可以編譯了。在終端進(jìn)入源文件目錄輸入make
運(yùn)行結(jié)果:
make[1]: Entering directory `/usr/src/linux-headers-2.6.24-24-generic'
CC [M] /home/yuqiang/桌面/mymodule/mymodules.o
LD [M] /home/yuqiang/桌面/mymodule/modules.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/yuqiang/桌面/mymodule/modules.mod.o
LD [M] /home/yuqiang/桌面/mymodule/modules.ko
make[1]: Leaving directory `/usr/src/linux-headers-2.6.24-24-generic'
第四步:加載/卸載我們的模塊
從上面的編譯中我可以看到。已經(jīng)有一個(gè)modules.ko生成了。這就是我們的模塊了。現(xiàn)在我們就可以來加載了。
首先在終端輸入:sudo insmod modules.ko
現(xiàn)在我們來看看我們的模塊加載成功沒有呢?
在終端輸入:dmesg | tail -12 這是查看內(nèi)核輸出信息的意思。tail -12 顯示最后12條;
顯示結(jié)果如下:
[17945.024417] sd 9:0:0:0: Attached scsi generic sg2 type 0
[18046.790019] usb 5-8: USB disconnect, address 9
[19934.224812] Hello, How are you. 0
[19934.224817] Hello, How are you. 1
[19934.224818] Hello, How are you. 2
[19934.224820] Hello, How are you. 3
[19934.224821] Hello, How are you. 4
[19934.224822] Hello, How are you. 5
[19934.224824] Hello, How are you. 6
[19934.224825] Hello, How are you. 7
[19934.224826] Hello, How are you. 8
[19934.224828] Hello, How are you. 9
看到了吧。我們的模塊的初始化函數(shù)yuer_init();已經(jīng)成功運(yùn)行了。說明我們的模塊已經(jīng)加載成功;
現(xiàn)在我們?cè)賮硇遁d模塊試試看。
在終端輸入:sudo rmmod modules
在終端輸入:dmesg | tail -3
[19934.224826] Hello, How are you. 8
[19934.224828] Hello, How are you. 9
[20412.046932] I come from yuer's module, I have been unlad.
可以從打印的信息中看到,我們的模塊的退出函數(shù)已經(jīng)被執(zhí)行了。說明我們的模塊已經(jīng)被成功的卸載了。到目前位置我們就已經(jīng)算是對(duì)模塊的編譯到編譯運(yùn)行算是有了一個(gè)整體上的認(rèn)識(shí)了。對(duì)于以后深入的學(xué)習(xí)還是應(yīng)該有點(diǎn)幫助的。下面我們將在看看于模塊相關(guān)的一些簡(jiǎn)單的操作。
第五步:加載模塊時(shí)傳遞參數(shù)
在終端輸入:sudo insmod module_name.ko nbr=4
在終端輸入:dmesg | tail -6
顯示結(jié)果如下:
[20800.655694] Hello, How are you. 9
[21318.675593] I come from onefile module, I have been unlad.
[21334.425373] Hello, How are you. 0
[21334.425378] Hello, How are you. 1
[21334.425380] Hello, How are you. 2
[21334.425381] Hello, How are you. 3
這樣我們就可以看到在模塊加載的時(shí)候動(dòng)態(tài)設(shè)置了我們的一個(gè)變量。初始化函數(shù)中的循環(huán)只執(zhí)行了4次。
可能你會(huì)問我怎么知道一個(gè)模塊可以設(shè)置那些變量呢。當(dāng)然,你可以先不設(shè)變量加載一次。然后可以在終端輸入ls /sys/module//parameters/來查看。在這里我們是這樣輸入的
在終端輸入:ls /sys/moedle/modules/parameters/
顯示結(jié)果:
nbr
如果我們的模塊加載成功了。最后我們還可以通過modinfo來查看我們的模塊信息。如下
在終端輸入:sudo modinfo modules.ko
顯示結(jié)果:
filename: modules.ko
license: GPL
author: Yu Qiang
srcversion: 20E9C3C4E02D130E6E92533
depends:
vermagic: 2.6.24-24-generic SMP mod_unload 586
parm: nbr:int
總結(jié):
今天介紹的相關(guān)知識(shí)都好像有一點(diǎn)淺嘗轍止的感覺。因?yàn)檫@里主要是通過一條線式方式來講解了模塊編寫的相關(guān)過程,其實(shí)在這個(gè)過程中還有很多可以發(fā)散的地方。例如:
在寫到MODULE_AUTHOR("Yu Qiang")的時(shí)候,你應(yīng)該想到還有
MODULE_DESCRIPTION(模塊用途的簡(jiǎn)單描述);
MODULE_VERSION(模塊的版本字符串);
MODULE_ALIAS(模塊的別名);
...
在寫到module_param(nbr, int, S_IRUGO);的時(shí)候,你應(yīng)該想到還有
EXPORT_SYMBOL(name); 可以導(dǎo)出模塊的函數(shù),這也是模塊編寫的最終目的
...
在用到insmod 和 modinfo的時(shí)候。你應(yīng)該想到還有
depmod 分析可加載模塊的依賴性,并生成modules.dep文件和映射文件
modprobe Linux內(nèi)核添加刪除模塊
...
如果要成為一名專業(yè)的linux模塊開發(fā)人員,還要走很多的路,就看各位的了,祝大家學(xué)習(xí)順利。
-
嵌入式
+關(guān)注
關(guān)注
5060文章
18979瀏覽量
302236 -
Linux
+關(guān)注
關(guān)注
87文章
11213瀏覽量
208736 -
Makefile
+關(guān)注
關(guān)注
1文章
125瀏覽量
19158
原文標(biāo)題:少走彎路系列!嵌入式Linux 模塊編譯步驟入門
文章出處:【微信號(hào):gh_c472c2199c88,微信公眾號(hào):嵌入式微處理器】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論