linux驅動學習:1.核心樹的建立

來源:互聯網
上載者:User

 首先,為什麼要建立核心樹呢?因為我們知道驅動可以編譯進核心進行執行,也可以以模組的方式載入到核心裡進行執行。編寫驅動程式在2.6版本的核心與 2.4版本的核心有所不同,2.4版本的核心只需要有一套核心標頭檔就夠了,而2.6的核心的模組則要和核心原始碼樹中的目標檔案相串連,這樣,就需要一個建立一個核心樹,來提供上面這些目標檔案。所以首先我們要建立一個核心原始碼樹,而這個核心原始碼樹的建立有兩種方式:一,直接用發行版的核心原始碼包建立(也就是你裝的Linux
系統);二,用www.kernel.org上下的純淨版核心構造,這裡選擇第二種方式。因為,發行版廠商提供的核心原始碼包通常打了許多補丁,從而和你從 www.kernel.org上下的核心存在很大的差異。在某些情況下,有可能廠商的補丁會修改裝置驅動程式使用的核心API。而我們最終要一直 Linux系統到開發板上去,我們不會去移植髮行版提供的核心,我們只會移植從www.kernel.org下的核心,所以不論是從學習的角度,還是從以後移植Linux的角度,我們都選擇第二種辦法。好了,廢話少說,下面開始敘述建立核心樹的詳細過程。

       首先,用uname -r 查看當前運行核心的版本:
[root@localhost ~]# uname -r
2.6.18-53.el5
[root@localhost ~]#
        然後,從www.kernel.org上下一個和你當前運行版本一樣的核心,這裡可以看到我當前啟動並執行核心版本是2.6.18-53.el5,好,那我就下一個2.16.18.x的版本(必須有和當前啟動並執行版本有同樣的版本號碼,否則在載入模組時候insmod: error inserting '***.o'  :-l invalid module format這樣的錯誤)。
        下下來之後放在一個目錄下,我存放的目錄為:
[root@localhost linux]# pwd
/home/linux
         解壓:
[root@localhost linux]# tar xvzf linux-2.6.18.tar.gz
解壓完之後會產生linux-2.6.18目錄。進入這個目錄:
[root@localhost linux]# cd linux-2.6.18
拷貝當前系統的.config檔案到這個目錄下:
[root@localhost linux-2.6.18]# cp /usr/src/kernels/2.6.18-53.el5-i686/.config ./(ubantu版本下在/boot/config-2.6.32-28-generic-pae)
運行makemenuconfig
[root@localhost linux-2.6.18]# make menuconfig

去掉中的*
儲存退出。(用ESC鍵退出,Y儲存)
執行make
[root@localhost linux-2.6.18]# make
時間一個多小時,可以去看電影去了。
[root@localhost linux-2.6.18]# make bzImage(此處i要大寫,編譯壓縮形式的核心)
[root@localhost linux-2.6.18]# make modules    (編譯選擇的模組)
[root@localhost linux-2.6.18]# make  modules_install  (將編譯後的模組轉移到系統標準位置,模組在系統中的標準目錄位於/lib/modules/x.y.z,後面的x.y.z是版本號碼,為安全起見,在運行#make modules-install之前最好對/lib/modules進行備份。模組通常是帶有副檔名.o的檔案,使用命令#lsmod可以對當前核心的模組進行列表。 )
可以看到在
[root@localhost code]# cd /lib/modules/
產生了2.6.18目錄
[root@localhost modules]# ls
2.6.18  2.6.18-53.el5  2.6.18.8
下面編寫一個hello模組
[root@localhost code]# gedit hello.c

view plaincopy to clipboardprint?
  1. #include <linux/init.h>    
      
  2. #include <linux/module.h>    
      
  3. MODULE_LICENSE("Dual BSD/GPL");      
  4. static int hello_init(void)      
  5. {      
  6. printk(KERN_EMERG "Hello, li wei meng/n");      
  7. return 0;      
  8. }      
  9. static void hello_exit(void)      
  10. {      
  11. printk(KERN_EMERG"Goodbye, li wei meng/n");      
  12. }      
  13. module_init(hello_init);      
  14. module_exit(hello_exit);       

#include <linux/init.h><br />#include <linux/module.h><br />MODULE_LICENSE("Dual BSD/GPL");<br />static int hello_init(void)<br />{<br />printk(KERN_EMERG "Hello, li wei meng/n");<br />return 0;<br />}<br />static void hello_exit(void)<br />{<br />printk(KERN_EMERG"Goodbye, li wei meng/n");<br />}<br />module_init(hello_init);<br />module_exit(hello_exit);<br />

這個模組什麼也不幹,只是在模組載入時列印一條資訊,卸載時也列印一條資訊。麻雀雖小,但五髒具全,MODULE_LICENSE()指明認證方式,現在支援的有:“GPL” “GPL v2" "GPL and additional rights" "Dual BSD/GPL" "Dual MIT/GPL" "Dual MPL/GPL" "Proprietary",這是核心2.6裡新添加的,實驗發現它不是必需的。module_init()指明模組的入口,這是必需的;module_exit()指明模組的出口,這也是必需的。

 

同時編寫Makefile,在同一目錄下:
[root@localhost code]# gedit Makefile

view plaincopy to clipboardprint?
  1. ifneq ($(KERNELRELEASE),)    
  2. obj-m := hello.o    
  3. else    
  4.     KDIR := /lib/modules/2.6.18/build    
  5. all:    
  6.     make -C $(KDIR) M=$(PWD) modules    
  7. clean:    
  8.     rm -f *.ko *.o *.mod.o *.mod.c *.symvers    
  9. endif    

ifneq ($(KERNELRELEASE),)<br />obj-m := hello.o<br />else<br /> KDIR := /lib/modules/2.6.18/build<br />all:<br /> make -C $(KDIR) M=$(PWD) modules<br />clean:<br /> rm -f *.ko *.o *.mod.o *.mod.c *.symvers<br />endif

其中KDIR指明了引用標頭檔的位置,請根據具體情況修改該檔案。不過有幾點要說明,模組的編譯需要有一個核心源碼的目錄結構,如果有核心源碼當然更好,直接把KDIR改為源碼的路徑就OK了。當然只有一個核心目錄結構也就可以了,畢竟需要的只是標頭檔,及一些編譯指令碼,在Linux各發行版的/usr/src/下是有這樣一個目錄結構的,比如我的系統為Ubuntu9.10,核心為2.6.31-19的通用版,在 /usr/src/下就有linux-headers-2.6.31-19-generic這樣一個目錄。所以我使用KDIR=/usr/src
/linux-headers-2.6.31-19-generic。其實還有一個目錄名為linux-headers-2.6.31-19,而且你會發現linux-headers-2.6.31-19-generic裡的大部分檔案只是指向linux-headers-2.6.31-19的一些連結,不過linux-headers-2.6.31-19裡面預設缺少一些編譯模組所需要的檔案,不要使用它。(切記:Makefile每個命令的第一個字元必須是定位字元[tab]即 KDIR,make,rm前不是四個空格空格開頭而是一個[tab],不要想當然的隨便認為只是個空格。否則會在編譯是報出***missing seperater .stop.
的錯誤 )執行make

[root@localhost code]# make
make -C /lib/modules/2.6.18/build M=/home/code modules
make[1]: Entering directory `/home/linux/linux-2.6.18'
  CC [M]  /home/code/hello.o
  Building modules, stage 2.
  MODPOST
  CC      /home/code/hello.mod.o
  LD [M]  /home/code/hello.ko
make[1]: Leaving directory `/home/linux/linux-2.6.18'執行insmod

[root@localhost code]# insmod hello.ko
[root@localhost code]#
Message from syslogd@ at Sun May 23 21:02:30 2010 ...
localhost kernel: Hello, li wei meng
 使用 insmod ./hello.ko來載入模組,如果你遇到insmod: error inserting 'hello.o'  :-l invalid module format這樣的錯誤,不用驚慌,並不是你的模組有問題,而是你當前啟動並執行核心版本與你編譯連結的標頭檔版本不一致,所以會出現格式不對的問題。此時,你可以更換系統核心,也可以下載一個與系統版本一致的核心源碼重新編譯該模組。如果你沒有遇到任何問題,也沒有列印出任何資訊,那麼恭喜你,你的核心載入成功了,你可以使用lsmod命令來羅列出當前你系統載入的所有模組,相信你在列表中會找到hello的。你可能會疑惑,為什麼沒有如我們想像中的那樣,列印出"Hello,
World"?呵呵,這是因為printk並不會把列印內容列印到你當面的終端,要知道模組是運行在核心態的,而你所能面對的是使用者態,核心態的列印資訊需要通過log或者dmesg命令來查看,想看到列印結果,最簡單的方法是敲入dmesg命令,你就可以看到你所希望看到的資訊了,同時,你也可以開啟 /var/log/message這個檔案進行查看。

 

執行rmmod
[root@localhost code]# rmmod hello.ko
[root@localhost code]#
Message from syslogd@ at Sun May 23 21:02:46 2010 ...
localhost kernel: Goodbye, li wei meng

最後,使用rmmod hello來卸載模組,同樣,使用dmesg可以看到列印出的"Goodbye, cruel world"。

 

 

附:

Linux 有許多功能是通過模組的方式,  在需要時才載入 kernel。 如此可使 kernel 較為精簡,進而提高效率,以及保有較大的彈性。這些可動態載入的模組,通常是系統的裝置驅動程式。載入模組採用 insmod 指令,其常用文法如下。

 insmod [-fkmpsvxX] [-o<模組名稱>] [模組檔案]
 其中的參數解釋如下。
  -f:不檢查目前 kernel 版本與模組編譯時間的 kernel 版本是否一致,強制將模組載入。
  -k:將模組設定為自動卸載。
  -m:輸出模組的載入資訊。
  -p:測試模組是否能正確地載入 kernel。
  -s:將所有資訊記錄在系統記錄檔案中。
  -v:執行時顯示詳細的資訊。
  -x:要匯出模組的外部符號。
  -X:匯出模組所有的外部符號,此為預設定。
  • rmmod(卸載模組)指令
  Linux 把系統的許多功能編譯成一個個單獨的模組,待有需要時再分別載入它們,如果不再需要這些模組的時候,就可以使用 rmmod 命令來卸載這些模組。其文法如下。
  rmmod [-as] [模組名稱...]
  其使用參數說明如下。
  -a:刪除所有目前不需要的模組。
  -s:把資訊輸出至 syslog 常駐服務,而非終端機介面

 

 

附:參考文檔http://blog.chinaunix.net/link.php?url=http://www.91linux.com%2Fhtml%2Farticle%2Fkernel%2F20071204%2F8805.html

                        http://www.huomo.cn/os/article-10f16.html

                        http://blog.csdn.net/liangkaiming/archive/2010/10/13/5937929.aspx

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.