Linux驅動靜態編譯和動態編譯方法詳解


內核源碼樹的目錄下都有兩個文檔Kconfig和Makefile。分布到各目錄的Kconfig構成了一個分布式的內核配置數據庫,每個Kconfig分別描述了所屬目錄源文檔相關的內核配置菜單。在內核配置make menuconfig時,從Kconfig中讀出菜單,用戶選擇后保存到.config的內核配置文檔中。在內核編譯時,主Makefile調用這個.config,就知道了用戶的選擇。

上面的內容說明了,Kconfig就是對應著內核的配置菜單。假如要想添加新的驅動到內核的源碼中,能夠修改Kconfig,這樣就能夠選擇這個驅動,假如想使這個驅動被編譯,要修改Makefile。所以,添加新的驅動時需要修改的文檔有兩種(注意不只是兩個)*Kconfig,*Makefile

.config是make menuconfig【配置后生成的一個配置文件,也就是說可以拷貝一個別人配置好的.config來使用,內核中不同開發板也自帶了一些配置文件在arch/arm/config/目錄下面有很多配置文件可以選擇和自己單板相似。

第一種方法:

利用內核自身的Makefile特性來編譯我們的驅動程序,下面由一個簡單的hello.c驅動程序來說明。

在/drivers/char/目錄下寫hello.c ?修改Makefile,Kconfig

hello.c內容:
#include <Linux/init.h> ? ? ? ? ? /* 初始化模塊所用到的頭文件 */
#include <linux/module.h> ? /* KERN_ALERT用到的 頭文件*/

static int hello_init(void) ? ? ?/* 入口函數,加載驅動程序所調用的函數 */

{
??????? printk(KERN_ALERT"Hello, world\n");
??????? return 0;
}


static void hello_exit(void) ? ? /* 出口函數 ,卸載驅動程序所調用的函數?*/
{

??????? printk(KERN_ALERT"Goodbye, cruel world\n");
}

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("Dual BSD/GPL"); ? /* 通用的協議 */

MODULE_AUTHOR("wangluoren"); ? ? /* 作者 */

MODULE_DESCRIPTION("A simple hello world module"); ? /* 程序描述 */

MODULE_ALIAS("A simplest module"); ? ? ? ? ? ? /* 別名 */


Kconfig內容:
config HELLO ? ? ? ? ? /* Makefile中編譯可變選項中宏的名字,作用就是定義一個可以選擇的變量 */
tristate "Hello Driver added by Dong" ? ? ? ?/* make menuconfig 菜單界面顯示的信息,tristate 提供Y M N三種選項?*/
default n ? ? ? ? ? /* 菜單選項默認為N */
help
?? test for adding driver to menuconfig. ? ? /* 一些幫助信息,寫不寫沒有關系 */


MakeFile內容:?
obj-$(CONFIG_HELLO) += hello.o ? ? /*CONFIG_HELLO我們在Kconfig中區定義它,我們用 HELLO ,hello是文件名字*/

到此為止我們就寫好了這個hello的驅動程序,然后我們可以make menuconfig 在

Device Drivers ?--->

?Character devices ?--->

<?> Hello Driver added by Dong ??/* 可以按空格選擇Y M N ,來分別 編譯進內核,模塊,不編譯*/

如果是直接編譯進內核就可以執行make uImage ,如果是編譯成模塊就執行make modules.


上面我們采用的是靜態編譯方法看起來是那么的麻煩,當我們寫驅動程序的時候如果采用這種方法的話那就夠折騰了,我估計你調試一個驅動程序你都得折騰大半天,這種方法是我們確定我們驅動程序沒有問題后在編譯進內核。

第二種方法:

一般我們采用動態編譯來寫驅動程序,具體方法如下:

還是拿hello.c程序為例:

hello.c內容:
#include <linux/init.h> ? ? ? ? ? /* 初始化模塊所用到的頭文件 */
#include <linux/module.h> ? /*?KERN_ALERT用到的 頭文件*/

static int hello_init(void) ? ? ?/* 入口函數,加載驅動程序所調用的函數 */

{
??????? printk(KERN_ALERT"Hello, world\n");
??????? return 0;
}


static void hello_exit(void) ? ? /* 出口函數 ,卸載驅動程序所調用的函數?*/
{

??????? printk(KERN_ALERT"Goodbye, cruel world\n");
}

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("Dual BSD/GPL"); ? /* 通用的協議 */

MODULE_AUTHOR("wangluoren"); ? ? /* 作者 */

MODULE_DESCRIPTION("A simple hello world module"); ? /* 程序描述 */

MODULE_ALIAS("A simplest module"); ? ? ? ? ? ? /* 別名 */


Makefile文件編寫如下:(和hello.c放在同一層目錄就OK)

KERN_DIR = /home/book/workspace/kernel/linux-3.4.2_jz2440 ? /* 虛擬機kernel的路徑,每個人不一樣 */

all:
? ? ? ? make -C $(KERN_DIR) M=`pwd` modules ? /* -C 表示進入后面KERN_DIR這個目錄把當前路徑的hello.c編譯成模塊*/

clean:
? ? ? ? make -C $(KERN_DIR) M=`pwd` modules clean ?/* 一些清除工作,清除中間生成的中間文件 */
? ? ? ? rm -rf modules.order
obj-m ? += hello.o ? ? ? ? ? ? ? ? ? ? ? ?/* 編譯,這里要注意這個hello是你要編譯的程序的文件名字 */?


上面兩種方法編譯完成后都會生成一個hello.ko的文件,我們把這個文件復制到開發板的目錄下面,執行如下命令 ? ? ?insmod hello.ko ?就會打印:Hello, world

rmmod hello ? ?就會打印 ?Goodbye, cruel world ?(這個是一一對應的,加載一次只能卸載一次,不能重復加載)


補充一:

動態加載補充一點:如果我要用一個Makefile同時編譯多個文件該怎么辦呢?(這個文件的一個函數在另外一個文件當中定義,我們可以采取如下方法)方法如下:

有來個驅動文件:hello.c ?hello1.c

我們可以把上面Makefile中obj-m +=hello.o改成如下命令就可以了

obj-m :=led.o
module-objs :=hello.o hello1.o ? /* 這時候生成的 驅動文件就是led.ko */


補充二:

如果同時又兩個驅動程序都需要編譯(兩者之間沒有任何聯系的,就是共同用kernel來編譯自己的驅動)

比如有兩個文件:hello1.c ?hello2.c?

我們可以在同一個Makefile中這樣來編寫:

obj-m+=hello1.o
obj-m += hello2.o ? ?(注意這個:=已經變成+=,這兩者的區別這里就不說明了)


補充三:

上面靜態編譯驅動我們采用的是在/drivers/char目錄下面添加一個文件,我們也可以在/drivers目錄下面添加一個文件夾,下面我們講講具體的怎么來實現。

我們在/drivers目錄下面添加一個hello的文件夾,里面創建一個hello.c,Kconfig,Makefile,這個三個文件和靜態編譯添加一個文件是完全相同的,主要是更改的是/drivers目錄下的Makefile和Kconfig文件。

Makefile中添加如下命令:

obj-$(CONFIG_HELLO) += hello/ ? ? ? ?/* CONFIG_HELLO這個宏定義在hello目錄里面的Kconfig中,‘/’表示進入這個目錄,調用子目錄Makefile來編譯子目錄中的文件?*/

Kconfig添加如下命令:

source "drivers/hello/Kconfig" ? ? /* 把Kconfig導出到子菜單界面 */

然后執行make modules ? 就在drivers/hello目錄下面生成了一個hello.ko的文件

現在這個驅動編譯的全部用法基本講解完畢,有了這些知識你自己都可以去分析內核的結構,從頂層Makefile開始分析,子目錄下的Makefile想對簡單的多,頂層Makefile是比較難的,頂層Makefile講解在這篇文章中,請點擊這里!


上面講解了一些基礎的知識,這些知識對一個驅動開發成員已經足夠了,如果你是工作在內核空間,那你就應該深入分析這些結構的原理,比如怎么添加遞歸創建子目錄,通配符,正則表達式等,你都需要去深入了解。希望我這篇文章能給驅動開發者帶來幫助。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/252925.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/252925.shtml
英文地址,請注明出處:http://en.pswp.cn/news/252925.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux學習-11月12日(Apache安裝)

2019獨角獸企業重金招聘Python工程師標準>>> 11.6 MariaDB安裝 11.7/11.8/11.9 Apache安裝 擴展 apache dso https://yq.aliyun.com/articles/6298 apache apxs https://wizardforcel.gitbooks.io/apache-doc/content/51.html apache工作模式 https://blog.csdn.…

11. sql DDL

SQL分為5大類&#xff1a; DDL:數據定義語言 DCL:數據控制語言 DML:數據操縱語言 DTL:數據事務語言 DQL:數據查詢語言 1、DDL(data definition language):create,drop,alter,rename to 數據類型 ①、數字類型&#xff0c;可以數學運算 number&#xff08;4&#xff09;代表整數…

[bzoj2243][SDOI2011]染色

來自FallDream 的博客&#xff0c;未經允許&#xff0c;請勿轉載&#xff0c;謝謝qaq 給定一棵有n個節點的無根樹和m個操作&#xff0c;操作有2類&#xff1a; 1、將節點a到節點b路徑上所有點都染成顏色c&#xff1b; 2、詢問節點a到節點b路徑上的顏色段數量&#xff08;連續相…

Linux學習筆記——例說makefile 增加宏定義

從學習C語言開始就慢慢開始接觸makefile&#xff0c;查閱了很多的makefile的資料但總感覺沒有真正掌握makefile&#xff0c;如果自己動手寫一個makefile總覺得非常吃力。所以特意借助博客總結makefile的相關知識&#xff0c;通過例子說明makefile的具體用法。 例說makefile…

Android基本組件是什么?

1、ImageView繼承View組件,不單單用于顯示圖片,用 XML代碼 編寫的Drawable也可以顯示出來。其中的XML屬性 android:scaleType(設置圖片如何縮放或移動以適應ImageView的大小) 有很多的屬性值,如:matrix(使用矩形方式進行縮放)fitXY(對圖片橫向縱向縮放)center(圖片放在ImageVie…

Java 運算符及優先級

運算符 分割符&#xff1a;  ,  ;  []  ()算數運算符&#xff1a;    -  *  /  %    --關系運算符&#xff1a;  >  <  >  <    !邏輯運算符&#xff1a;  !  &  |  ^  &&  ||賦值運算符&#xff1a; …

array sort - 2 : quick sort

遞歸實現&#xff1a; #include <stdio.h>int arr[10] {3, 2, 4, 1, 9, 7, 5, 6, 0, 8};void print_array(){ int i 0; for (i 0; i < 10; i) printf("arr[%d]:%d ", i, arr[i]); printf("\n");}void swap(int *i, int *j){ …

Linux C 讀取文件夾下所有文件(包括子文件夾)的文件名

本文&#xff1a;http://www.cnblogs.com/xudong-bupt/p/3504442.html Linux C 下面讀取文件夾要用到結構體struct dirent&#xff0c;在頭#include <dirent.h>中&#xff0c;如下&#xff1a; #include <dirent.h> struct dirent {long d_ino; /* inode number 索…

報表工具實現單據套打

【摘要】 單據套打再也不用手動測量&#xff0c;反復調試了&#xff0c;報表工具實現單據套打&#xff0c;去乾學院看個究竟&#xff1a;報表工具實現單據套打!實際項目開發中&#xff0c;很多情況會涉及到單據的打印。即在一張印刷好的空白單據上&#xff0c;準確無誤地打印上…

每隔10秒鐘打印一個“Helloworld”

/*** 每隔10秒鐘打印一個“Helloworld”*/ public class Test03 {public static void main(String[] args) throws InterruptedException {ThreadImp threadImp new ThreadImp();Thread thread1 new Thread(threadImp);thread1.start();} }class ThreadImp extends Thread {p…

C++ STL 優先隊列

//優先隊列//Priority_queue //STL#include<iostream>#include<cstdio>#include<cstdlib>#include<queue>using namespace std;struct cmp{ bool operator() (const int a,const int b) const{//用const定義的a,b是包裹著變量外衣的常數&#xff0c;不…

GDB調試core文件樣例(如何定位Segment fault)

core dump又叫核心轉儲, 當程序運行過程中發生異常, 程序異常退出時, 由操作系統把程序當前的內存狀況存儲在一個core文件中, 叫core dump. (Linux中如果內存越界會收到SIGSEGV信號&#xff0c;然后就會core dump) 在程序運行的過程中&#xff0c;有的時候我們會遇到Segment fa…

管理信息系統的開發與管理

{% extendsmuban.html %} {% block head %}輸入{% endblock %} {% block main %} <div><div class"form-group"><label for"question">標題</label><textarea class"form-control" cols"50" rows"2&q…

python11-28筆記(1.6-1.7)

1.6 多類型傳值和冗余參數多類型傳值&#xff1a;比如def fun(x,y)&#xff0c;定義2個形參定義一個元組t(1,2),如果把元組當做實參傳入到函數中&#xff0c;會報錯 如何將元組當做不同類型的參數傳入到函數中fun(t) 代表傳入的是元組或者這樣調用fun((1,2))注意實參的個數要和…

session機制詳解以及session的相關應用

session是web開發里一個重要的概念&#xff0c;在大多數web應用里session都是被當做現成的東西&#xff0c;拿來就直接用&#xff0c;但是一些復雜的web應用里能拿來用的session已經滿足不了實際的需求&#xff0c;當碰到這樣的情況時候我們需要更加深入的理解session的機制&am…

(轉)Shell中獲取字符串長度的七種方法

Shell中獲取字符串長度的七種方法 原文&#xff1a;http://blog.csdn.net/jerry_1126/article/details/51835119 求字符串操作在shell腳本中很常用&#xff0c;下面歸納、匯總了求字符串的幾種可能方法: 【方法一】:利用${#str}來獲取字符串的長度 【方法二】:利用awk的length方…

linux下用core和gdb查詢出現段錯誤的地方

有些時候我們在一段C代碼的時候&#xff0c;由于對一個非法內存進行了操作&#xff0c;在程序運行的過程中&#xff0c;出現了"段錯誤"。呵呵&#xff0c;這種問題我想很多人會經常遇到。遇到這種問題是非常無語的&#xff0c;只是提示了"段錯誤"&#xff…

第一篇-Html標簽中head標簽,body標簽中input系列,textarea和select標簽

第十四周課程&#xff08;1-12章節&#xff09; HTML 裸體 CSS 穿華麗衣服 Javascript 動起來 一 HTML &#xff08;20個標簽&#xff09; 1.我們的瀏覽器是socket客戶端 2.一套規則&#xff0c;瀏覽器認識的規則 3.開發者&#xff1a; 學習html規則 開發后臺程序&#xff1a…

opencv3.2.0 Cmake 3.8.0 + tdm-gcc-5.1.0-3

實測 tdm-gcc-5.1.0-3 tdm32-1 32位版本無法正確編譯Opencv 3.2.0 會遇到諸多編譯問題 解決辦法 使用tdm-gcc-5.1.0-2 tdm64-1 64位版本轉載于:https://www.cnblogs.com/fundou/p/6710209.html

什么是商品屬性

一、什么是商品屬性&#xff1a; Definition of Product Attributes A product attribute is a characteristic that defines a particular product and will affect a consumers purchase decision. Product attributes can be tangible (or physical in nature) or intangibl…