編寫內核模塊及安裝查看卸載過程

以前咱們寫的代碼都是直接編譯到內核中,這樣每次都要進行內核的從新編譯,而且還要刷機纔可以看到效果,非常麻煩.這回咱們來學習一下如何直接編譯一段代碼,以模塊的方式安裝到內核執行:linux

  一個文件編譯成一個內核模塊:vim

  找一個文件夾:touch module_test1.c Makefile數組

  vim module_test1.cide

  1 #include <linux/init.h>
  2 #include <linux/module.h>
  3 #include <linux/sched.h>
  4 
  5 //當模塊安裝的時候執行
  6 static __init int test_init(void)
  7 {
  8         printk("test_init\n");
  9         return 0;
 10 }
 11 //當模塊卸載的時候執行
 12 static __exit int test_exit(void)
 13 {
 14         printk("test_exit\n");
 15         return 0;
 16 }
 17 //註冊這兩個函數
 18 module_init(test_init);
 19 module_exit(test_exit);
 20 //聲明開源規則
 21 MODULE_LICENSE("GPL");

  vim Makefile函數

  1 LINUX_SRC :=/home/liuye/tiny4412/FriendlyARM_kernel/linux-3.5  #指定咱們板子上用的內核路徑,使用這個內核編譯的代碼才能成功運行在咱們的板子上.
  2 obj-m   += module.o            #生成module.ko   但咱們寫module.o就能夠
  3 module-objs=module_test1.o     #這裏寫要編譯文件
  4 #obj-m +=module_test1.o        #這是單文件的編譯:上面兩行是多文件的編譯,更加方便
  5 
  6 all:
  7         make -C $(LINUX_SRC) M=`pwd` modules
  8 clean:
  9         make -C $(LINUX_SRC) M=`pwd` modules clean

  make  生成 module.ko學習

  cp module.ko /myroot/liuye     即nfs共享路徑下   運行看下效果吧this

root@board liuye_dir#insmod module.ko 
[ 3817.370000] test_init
root@board liuye_dir#lsmod
Module                  Size  Used by    Tainted: G  
module                   740  0 
root@board liuye_dir#rmmod module.ko 
[ 3821.550000] test_exit
root@board liuye_dir#

 /*****************************************************************************************************************************************************************************************************/spa

多個文件編譯成一個內核模塊:code

  touch module_test1.c module_test2.c Makefileblog

  vim module_test1.c 調用module_test2.c內的函數 

  1 #include <linux/init.h>
  2 #include <linux/module.h>
  3 #include <linux/sched.h>
  4 //內核代碼中不容許有警告,由於在編譯的時候多是警告,可是在邏輯尚有多是個錯誤
  5 extern int my_print(int no);
  6 //當模塊安裝的時候執行
  7 static __init int test_init(void)
  8 {
  9         printk("test_init\n");
 10         my_print(5);
 11         return 0;
 12 }
 13 //當模塊卸載的時候執行
 14 static __exit int test_exit(void)
 15 {
 16         printk("test_exit\n");
 17         return 0;
 18 }
 19 //註冊這兩個函數
 20 module_init(test_init);
 21 module_exit(test_exit);
 22 //聲明開源規則
 23 MODULE_LICENSE("GPL");

  vim module_test2.c

  1 #include <linux/init.h>
  2 #include <linux/module.h>
  3 #include <linux/sched.h>
  4 int my_print(int no)
  5 {
  6         int i;
  7         for(i=0;i<no;i++)
  8         {
  9                 printk("no=%d\n",no);
 10         }
 11         return 100;
 12 }

  vim Makefile

  1 LINUX_SRC :=/home/liuye/tiny4412/FriendlyARM_kernel/linux-3.5
  2 obj-m   += module.o            #生成module.ko   但咱們寫module.o就能夠
  3 module-objs=module_test1.o  module_test2.o   #這裏寫要編譯的文件
  4 #obj-m +=module_test1.o        #這是單文件的編譯:上面兩行是多文件的編譯,更加方便
  5 
  6 all:
  7         make -C $(LINUX_SRC) M=`pwd` modules
  8 clean:
  9         make -C $(LINUX_SRC) M=`pwd` modules clean

  make  生成module.ko 到開發板上安裝查看卸載  

root@board liuye_dir#insmod module.ko 
[ 5324.040000] test_init
[ 5324.040000] no=5
[ 5324.040000] no=5
[ 5324.040000] no=5
[ 5324.040000] no=5
[ 5324.040000] no=5
root@board liuye_dir#lsmod
Module                  Size  Used by    Tainted: G  
module                   913  0 
root@board liuye_dir#rmmod module.ko 
[ 5327.515000] test_exit
root@board liuye_dir#

 /*****************************************************************************************************************************************************************************************************/

多個文件編譯成多個內核模塊:

  vim module_test1.c

  1 #include <linux/init.h>
  2 #include <linux/module.h>
  3 #include <linux/sched.h>
  4 //內核代碼中不容許有警告,由於在編譯的時候多是警告,可是在邏輯尚有多是個錯誤
  5 extern int my_print(int no);
  6 //當模塊安裝的時候執行
  7 static __init int test_init(void)
  8 {
  9         printk("test_init\n");
 10         my_print(5);
 11         return 0;
 12 }
 13 //當模塊卸載的時候執行
 14 static __exit int test_exit(void)
 15 {
 16         printk("test_exit\n");
 17         return 0;
 18 }
 19 //註冊這兩個函數
 20 module_init(test_init);
 21 module_exit(test_exit);
 22 //聲明開源規則
 23 MODULE_LICENSE("GPL");

  vim module_test2.c

  1 #include <linux/init.h>
  2 #include <linux/module.h>
  3 #include <linux/sched.h>
  4 static __init int test_init(void)
  5 {
  6         return 0;
  7 }
  8 static __exit int test_exit(void)
  9 {
 10         return 0;
 11 }
 12 int my_print(int no)
 13 {
 14         int i;
 15         for(i=0;i<no;i++)
 16         {
 17                 printk("no=%d\n",no);
 18         }
 19         return 100;
 20 }
 21 //模塊之間的關係要進行符號導出
 22 //模塊1調用了模塊2內部的函數my_print,雖然函數以前沒有添加static修飾,可是在模塊之間調用,至關於的添加了static修飾,因此該函數不支持其餘模塊的調用,
    只支持當前文件和當前模塊的調用.因此模塊2安裝完成,模塊1依然insmod不上,爲了解決模塊1依賴模塊2的問題,因此要進行符號導出.
    咱們寫的驅動程序都須要調用內核提供的方法,內核裏面的方法都是通過符號導出的.
23 //其中module_init和module_exit是宏實現的:宏定義在:#include<linux/module.h>中 24 EXPORT_SYMBOL(my_print); 25 module_init(test_init); 26 module_exit(test_exit); 27 MODULE_LICENSE("GPL"); ~

  vim Makefile

  1 LINUX_SRC :=/home/liuye/tiny4412/FriendlyARM_kernel/linux-3.5
  2 #obj-m  += module.o            #生成module.ko   但咱們寫module.o就能夠
  3 #module-objs=module_test1.o  module_test2.o   #這裏寫要編譯文件
  4 obj-m +=module_test1.o module_test2.o       #這是單文件的編譯會生成多個ko:上面兩行是多文件的編譯,更加方便
  5 
  6 all:
  7         make -C $(LINUX_SRC) M=`pwd` modules
  8 clean:
  9         make -C $(LINUX_SRC) M=`pwd` modules clean

  在安裝的時候要先安裝模塊2在安裝模塊一,在卸載的時候要先卸載模塊1再卸載模塊2;

  解釋depmod:請參見另外一片文章

  modprobe:

  以及內核傳參數的代碼請查看另外一篇文章:

 /*****************************************************************************************************************************************************************************************************/

 

  1 LINUX_SRC :=/home/liuye/tiny4412/FriendlyARM_kernel/linux-3.5
  2 #obj-m  += module.o            #生成module.ko   但咱們寫module.o就能夠
  3 #module-objs=param.o     #這裏寫要編譯文件
  4 obj-m +=param.o param1.o       #這是單文件的編譯:上面兩行是多文件的編譯,更加方便
  5 
  6 all:
  7         make -C $(LINUX_SRC) M=`pwd` modules
  8 clean:
  9         make -C $(LINUX_SRC) M=`pwd` modules clean
makefile
  1 #include <linux/init.h>
  2 #include <linux/module.h>
  3 #include <linux/sched.h>
  4 
  5 static __init int test1_init(void)
  6 {
  7         printk("this is liuye test1_init\n");
  8         return 0;
  9 }
 10 static __exit void test1_exit(void)
 11 {
 12         printk("this is liuye test1_exit\n");
 13 }
 14 
 15 module_init(test1_init);
 16 module_exit(test1_exit);
 17 MODULE_LICENSE("GPL");
 18 void my_print(int no)
 19 {
 20         printk("no = %d\n",no);
 21 }
 22 EXPORT_SYMBOL(my_print);
param1.c
  1 #include <linux/init.h>
  2 #include <linux/module.h>
  3 #include <linux/sched.h>
  4 extern void my_print(int name);
  5 
  6 int name=0;
  7 char *buf;
  8 bool boolc;
  9 int arr[10];
 10 int len;
 11 //module_param_named(name,name,int,0);
 12 //module_param_named(buf,buf,charp,0);
 13 //module_param_named(boolc,boolc,bool,0);
 14 
 15 module_param(name,int,0660);
 16 module_param(buf,charp,0660);
 17 module_param(boolc,bool,0660);
 18 module_param_array(arr,int,&len,0660);
 19 static __init int test_init(void)
 20 {
 21         int i;
 22         printk("this is liuye test_init\n");
 23 //      my_print(name);
 24         printk("name =%d\n",name);
 25         printk("buf =%s\n",buf);
 26         printk("boolc =%d\n",boolc);
 27         for(i=0;i<len;i++)
 28         {
 29                 printk("arr[%d]=[%d]\n",i,arr[i]);
 30         }
 31         printk("len =%d\n",len); //這裏的長度,等於實際輸入的數組元素個數
 32         my_print(333333)        
 33         return 0;
 34 } 
 35 static __exit void test_exit(void)
 36 {
 37         int i;
 38         printk("this is liuye test_exit\n");
 39 //      my_print(name);
 40         printk("name =%d\n",name);
 41         printk("buf =%s\n",buf);
 42         printk("boolc =%d\n",boolc);
 43         for(i=0;i<len;i++)
 44         {
 45                 printk("arr[%d]=[%d]\n",i,arr[i]);
 46         }
 47         printk("len =%d\n",len); //這裏的長度,等於實際輸入的數組元素個數
 48         
 49 }
 50 
 51 module_init(test_init);
 52 module_exit(test_exit);
 53 MODULE_LICENSE("GPL");
param.c
相關文章
相關標籤/搜索