Linux 驅動開發內核模塊的添加

今天從網上看了個視頻教程,關於內核模塊開發的。網絡上有許多這樣的文章,應該比我這個詳細。

寫這篇博客的目的是做一下筆記,便於自己查閱。

首先給出內核模塊源代碼,當然是最最簡單的helloworld。

   #include <linux/init.h>   

   #include <linux/module.h>   

     

   MODULE_LICENSE("GPL");  //GPL 開源協議

    

    static int hello_init(void)  

   {  

        printk(KERN_ALERT "hello module!\n");  //內核打印信息函數,相當於應用層的printf();

     return 0;  

}  

 

 static void hello_exit(void)  

{  

   printk(KERN_ALERT "bye module!\n");  

 }  

  

 module_init(hello_init);  //必須使用的,模塊加載函數。向內核註冊

 module_exit(hello_exit);  //必須使用的,模塊卸載函數註冊


需要的Makefile

ifneq ($(KERNELRELEASE),)    //判斷KERNELRELEASE不能與NULL

obj-m:=hello.o   //目標模塊的名稱

else

#generate the path

CURRENT_PATH:=$(shell pwd)  //獲得當前目錄的名稱並賦值給CURRENT_PATH變量

#the absolute path  // 是用絕對路徑

LINUX_KERNEL_PATH:=/lib/modules/$(shell uname -r)/build      //內核模塊所依賴的內核編譯路徑,shell uname -r獲得當前內核版本號

#complie object

default:

make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules //make -C 表示到$(LINUX_KERNEL_PATH)使用它的makefile編譯。

                                                                                                                             //M=$(CURRENT_PATH)表示你的內核源代碼的位置

                                                                                                                             // modules :編譯成爲模塊

clean:

make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean

endif

編譯一次內核模塊需要兩次執行上述makefile,第一次執行的時候KERNELRELEASE是沒有值得,第二次執行時KERNELRELEASE是有值得。需要

注意此處



如果多個C文件進行的編譯一個內核模塊。Makefile則需要寫爲如下格式


ifneq ($(KERNELRELEASE),)    //判斷KERNELRELEASE不能與NULL

obj-m:=hello.o   //目標模塊的名稱

hello.o-objs :=file1.o file2.o file3.o  ...  //(可以最近多個)       ------>如果一個源文件可以用這個方式生產與文件名不同的內核模

else

#generate the path

CURRENT_PATH:=$(shell pwd)  //獲得當前目錄的名稱並賦值給CURRENT_PATH變量

#the absolute path  // 是用絕對路徑

LINUX_KERNEL_PATH:=/lib/modules/$(shell uname -r)/build      //內核模塊所依賴的內核編譯路徑,shell uname -r獲得當前內核版本號

#complie object

default:

make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules //make -C 表示到$(LINUX_KERNEL_PATH)使用它的makefile編譯。

                                                                                                                             //M=$(CURRENT_PATH)表示你的內核源代碼的位置

                                                                                                                             // modules :編譯成爲模塊

clean:

make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean

endif


編譯得到hello.ko,然後insmod hello.ko加載模塊,rmmod hello卸載模塊。

查看內核模塊lsmod

modprobe hello:也是加載一個模塊,但是不同於insmod的是,它會在/lib/modules/$<$version>/modules.dep查看要加載的模塊,看

是否依賴於其他的模塊,如果有modprobe會先找到那些被依賴模塊並先安裝它們。

--------------------------------華麗的分割線---------------------------------------

內核參數

1.定義模塊參數的方法:

            module_param(name, type, perm);

            其中,name:表示參數的名字;
     type:表示參數的類型;
     perm:表示參數的訪問權限;


       static int num=10;
module_param(num,int,S_IRUGO);
static int hello_init(void)
{
    printk("Hello module init./n");
    printk("num=%d/n",num);
    return 0;
}
static void   hello_exit(void)
{
    printk("Goodbye module exit./n");
}
module_init(hello_init);
module_exit(hello_exit);

       MODULE_LICENSE("GPL");

       MODULE_DESCRIPTION("a simple module");
MODULE_ALIAS("hello");

shell    $ insmod hello.ko  num=100 即可改變num的值。

-------------------------------------------華麗分割線-----------------------------------

內核模塊符號導出

    EXPORT_SYMBOL(函數名/變量名

      即當一個內核模塊調用另外一個內核模塊的函數或者變量時,需要再被調用的內核模塊中將變量或者函數使用EXPROT_SYMBOL 將對應函數或者變量導出,才能

正常使用。關於這部分內容網絡上有許多博文,具體使用時請參考其他博文吧。


----------------------------華麗分割線----------------------------------------------

內核打印&級別。

/proc/sys/kernel/printk中定義着其他控制檯和其他log文件的打印級別。

其他的就不再贅述了,網上有很多博文了。

-----------------------------------華麗結束線-----------------------------------




發佈了26 篇原創文章 · 獲贊 39 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章