1. 程式人生 > >Linux驅動靜態編譯和動態編譯方法詳解

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

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

               

核心原始碼樹的目錄下都有兩個文件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講解在這篇文章中,請點選這裡!


上面講解了一些基礎的知識,這些知識對一個驅動開發成員已經足夠了,如果你是工作在核心空間,那你就應該深入分析這些結構的原理,比如怎麼新增遞迴建立子目錄,萬用字元,正則表示式等,你都需要去深入瞭解。希望我這篇文章能給驅動開發者帶來幫助。

           

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述