內核源碼樹的構建1





xuxinyl的專欄
目錄視圖摘要視圖訂閱
 linux驅動學習:1.內核樹的建立
標籤: linuxmodulemakefilesun終端2010
2011-11-21 14:10 3534人閱讀 評論(0) 收藏 舉報
 分類:  linux編程(15)  
 首先,爲什麼要建立內核樹呢?因爲我們知道驅動可以編譯進內核進行執行,也可以以模塊的方式加載到內核裏進行執行。編寫驅動程序在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


學習Linux驅動第一步:內核樹的建立
學習Linux驅動第一步:內核樹的建立


去掉上圖中的*
保存退出。(用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 clipboard
#include <linux/init.h>       
#include <linux/module.h>       
MODULE_LICENSE("Dual BSD/GPL");      
static int hello_init(void)      
{      
printk(KERN_EMERG "Hello, li wei meng/n");      
return 0;      
}      
static void hello_exit(void)      
{      
printk(KERN_EMERG"Goodbye, li wei meng/n");      
}      
module_init(hello_init);      
module_exit(hello_exit);       
[cpp] view plain copy
#include <linux/init.h>      
#include <linux/module.h>      
MODULE_LICENSE("Dual BSD/GPL");      
static int hello_init(void)      
{      
printk(KERN_EMERG "Hello, li wei meng/n");      
return 0;      
}      
static void hello_exit(void)      
{      
printk(KERN_EMERG"Goodbye, li wei meng/n");      
}      
module_init(hello_init);      
module_exit(hello_exit);       




這個模塊什麼也不幹,只是在模塊加載時打印一條信息,卸載時也打印一條信息。麻雀雖小,但五臟具全,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 clipboard
ifneq ($(KERNELRELEASE),)    
obj-m := hello.o    
else    
    KDIR := /lib/modules/2.6.18/build    
all:    
    make -C $(KDIR) M=$(PWD) modules    
clean:    
    rm -f *.ko *.o *.mod.o *.mod.c *.symvers    
endif    
[cpp] view plain copy
ifneq ($(KERNELRELEASE),)    
obj-m := hello.o    
else    
    KDIR := /lib/modules/2.6.18/build    
all:    
    make -C $(KDIR) M=$(PWD) modules    
clean:    
    rm -f *.ko *.o *.mod.o *.mod.c *.symvers    
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



0

0
上一篇解除android 2.2 每小時只能發100條短信的限制(轉)
下一篇make命令參數詳解
我的同類文章
linux編程(15)
•make命令參數詳解2011-11-22閱讀5890
•linux中fork()函數詳解(原創!!實例講解)2011-07-06閱讀891
•ubuntu安裝JDK及環境變量的配置2011-06-21閱讀2806
•linux PPP,PPPoE (翻譯,整理)2011-06-10閱讀2100
•linux下實現虛擬網卡TAP/TUN例子2011-05-30閱讀5941
•Gedit快捷鍵2011-07-12閱讀2210
•linux socket 通信編程2011-07-06閱讀355
•C調用Linux內核的錯誤errno2011-06-15閱讀468
•LINUX 虛擬網卡tun例子2011-05-30閱讀6242
更多文章
主題推薦linux驅動內核
猜你在找
Android底層技術:Linux驅動框架與開發嵌入式Linux高級驅動教程(韋東山2期)“攢課”課題3:安卓編譯與開發、Linux內核及驅動Linux操作系統及常用基礎命令深入講解Linux操作系統及常用命令實戰和進階
linux驅動學習之內核線程分析Linux驅動學習筆記二--kset內核對象集合LINUX驅動內核源碼樹構建linux驅動內核學習Linux驅動學習11內核中jiffies的迴繞問題
查看評論


  暫無評論


發表評論
用 戶 名:
heixiaolong7
評論內容:
插入代碼


  
* 以上用戶言論只代表其個人觀點,不代表CSDN網站的觀點或立場
核心技術類目
全部主題 Hadoop AWS 移動遊戲 Java Android iOS Swift 智能硬件 Docker OpenStack VPN Spark ERP IE10 Eclipse CRM JavaScript 數據庫 Ubuntu NFC WAP jQuery BI HTML5 Spring Apache .NET API HTML SDK IIS Fedora XML LBS Unity Splashtop UML components Windows Mobile Rails QEMU KDE Cassandra CloudStack FTC coremail OPhone CouchBase 雲計算 iOS6 Rackspace Web App SpringSide Maemo Compuware 大數據 aptech Perl Tornado Ruby Hibernate ThinkPHP HBase Pure Solr Angular Cloud Foundry Redis Scala Django Bootstrap
個人資料
 訪問我的空間 
xuxinyl
 
訪問:270919次
積分:3370
等級: 
排名:第5793名
原創:57篇轉載:64篇譯文:0篇評論:78條
文章搜索


文章分類
android 中間件開發學習筆記(11)
android 應用開發(17)
C/C++ Language(1)
linux編程(16)
網絡編程(4)
JAVA Language(3)
視頻(3)
android內核機制(1)
android系統開發(4)
文章存檔
2014年05月(4)
2012年05月(1)
2012年04月(3)
2012年03月(1)
2011年12月(1)
展開
閱讀排行
android NDK的android.mk文件的詳解(21290)
正確配置安裝和卸載Cygwin(12950)
android 彈出“應用程序×××無法響應”窗口的解析和解決方案(11679)
android 亮屏及屏幕解鎖代碼(10824)
android監聽用戶的撥打電話的狀態(8755)
android GPS定位,基站定位,WIFI定位開關的控制(7924)
android NDK 交叉編譯(7339)
LINUX 虛擬網卡tun例子(6244)
Android的/system/lib里加入自己的so庫(6159)
linux下實現虛擬網卡TAP/TUN例子(5950)
評論排行
android監聽用戶的撥打電話的狀態(23)
讀取聯繫人列表(7)
android 亮屏及屏幕解鎖代碼(4)
android 彈出“應用程序×××無法響應”窗口的解析和解決方案(3)
實現Launcher3的立方滾動特效(3)
android數據存儲(3)
LINUX 虛擬網卡tun例子(2)
android NDK的android.mk文件的詳解(2)
android發送與接收超長短信(2)
android ContentProvider共享數據方法(2)
推薦文章
*Android自定義ViewGroup打造各種風格的SlidingMenu
* Android 6.0 運行時權限處理完全解析
* 數據庫性能優化之SQL語句優化
*Animation動畫詳解(七)——ObjectAnimator基本使用
* Chromium網頁URL加載過程分析
* JavaScript “跑馬燈”抽獎活動代碼解析與優化(一)
最新評論
實現Launcher3的立方滾動特效
chengtingfei: 完全是扯淡,不看下launcher3 viewpager的源碼就扯呼
實現Launcher3的立方滾動特效
HelloKen: 我添加到Launcher3的PagedView裏面不生效啊。。。
make命令參數詳解
H100: 學習了
android 亮屏及屏幕解鎖代碼
baidu_18355515: 這種方法在沒有屏幕鎖的時候是可以的,一旦屏幕鎖密碼開啓,則不能解鎖,怎麼辦?
JNI的某些數組和字符串類型轉換(轉)
yaotang: 有幾個變量是什麼類型都沒有給出來,看不懂,有些懂
android NDK的android.mk文件的詳解
qq_20324851: 我想知道,Android.mk的文件在哪裏可以找到
實現Launcher3的立方滾動特效
hefangchi: 好文章
android NDK的android.mk文件的詳解
rainberda: 樓主給力
android的硬件按鈕的長按和短按事件
gaogaf: 這個 1s 是在哪裏定義的呢?
LINUX 虛擬網卡tun例子
KnowledgeSeekers: 你好,我想問一下,我現在創建了一個TUN接口,如果我更改了默認路由到這個tun設備上。。那之後所有的...
公司簡介|招賢納士|廣告服務|銀行匯款帳號|聯繫方式|版權聲明|法律顧問|問題報告|合作伙伴|論壇反饋
網站客服雜誌客服微博客服[email protected]|北京創新樂知信息技術有限公司 版權所有|江蘇樂知網絡技術有限公司 提供商務支持
京 ICP 證 09002463 號|Copyright © 1999-2014, CSDN.NET, All Rights Reserved GongshangLogo

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章