博客專欄

EEPW首頁 > 博客 > 編譯一個自己的內(nèi)核模塊,并加載進內(nèi)核

編譯一個自己的內(nèi)核模塊,并加載進內(nèi)核

發(fā)布人:電子禪石 時間:2020-06-24 來源:工程師 發(fā)布文章
內(nèi)核模塊編寫

分類: Linux 771人閱讀 評論(0) 收藏 舉報

本文檔的Copyleft歸rosetta所有,使用GPL發(fā)布,可以自由拷貝、轉(zhuǎn)載,轉(zhuǎn)載時請保持文檔的完整性。
參考資料:《Linux設備驅(qū)動程序 第三版》
來源:http://blog.csdn.net/rosetta/article/details/7563601

  以前也曾經(jīng)想過往Linux內(nèi)核編程方向長展,但總歸是沒有入門的機會,看過《Linux設備驅(qū)動程序》(買來已經(jīng)兩年多了),但就像看天書似的。
現(xiàn)在往網(wǎng)絡編程方面發(fā)展,涉及面還是挺廣的,這也是一次偶然的機會,上頭讓我把Ipsec的算法模塊整理下,雖然這工作做起來非常無聊,但還是讓我發(fā)現(xiàn)了和設備驅(qū)動相關的東西,讓我的精神為之一振,從而再次拿起《Linux設備驅(qū)動程序》來為我答疑。
最近還在看openswan klips的實現(xiàn),涉及到網(wǎng)卡驅(qū)動程序編寫,慢慢都給整理成筆記,今天先把這最基本的基礎知識先帖上。

知識點:
1.    編譯多個.c源文件的ko(單個文件編寫網(wǎng)上有太多的教程,多個c源文件編譯是這我這回遇到的)
2.    編寫帶參數(shù)的內(nèi)核模塊(這個順便也給記下,雖然貌似沒有用到)
3.    insmod,rmmod,mknod,modprobe,dmesg等命令使用(dmesg比較有用,有些人不知道用這個命令,就說要用串口顯示信息,其實dmesg命令更方便,-c選項清空信息)
4.    無法插入內(nèi)核的原因。(這個也是關鍵,很多時候操作起來比較簡單,比如編譯內(nèi)核源碼,但可能會碰到一系列錯誤,解決一堆錯誤最能提升一個人的能力)

一、編譯多個.c文件的ko模塊并插入內(nèi)核
   //test_module.c
  #include
  #include
 
  #include "extern_app.h"
 
  static char *who = "linux ss";
  static int many = 1;
  module_param(many, int, S_IRUGO);
  module_param(who, charp, S_IRUGO);
 
  static int __init hello_init(void)
  {
      test();
      static int i = 0;
 
      for(i = 0; i < many; i++)
          printk(KERN_ALERT "Hello, %s!\n", who);
 
      return 0;
  }
 
  static void __exit hello_exit(void)
  {
      printk(KERN_ALERT "Goodbye\n");
  }
 
  module_init(hello_init);
  module_exit(hello_exit);
  MODULE_LICENSE("GPL");

  //extern_app.c
  #include
  #include
  int test(void)
  {
      printk("test here.\n");
 
      return 0;
  }

  //extern_app.h
  #ifndef __EXTERN_APP_H
  #define __EXTERN_APP_H
 
  extern int test(void);
 
  #endif

  //Makefile
  #ifneq ($(KERNELRELEASE),)
      obj-m := my_module.o
      my_module-objs := test_module.o extern_app.o
  #else
  KERNELDIR ?= /lib/modules/$(shell uname -r)/build
  PWD := $(shell pwd)
 
  default:
      $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
 
  clean:
      rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions
      rm -rf Module.* modules.*
 
  .PHONY: default clean
  #endif

  make,如果執(zhí)行成功則生成my_module.ko
 
  //執(zhí)行insmod 后并調(diào)用dmesg,正常情況如下顯示:
  [root@localhost module_kernel]# insmod my_module.ko who=Coding many=5
  [root@localhost module_kernel]# dmesg
  test here.
  Hello, Coding!
  Hello, Coding!
  Hello, Coding!
  Hello, Coding!
  Hello, Coding!
  [root@localhost module_kernel]#

  //rmmod從內(nèi)核移除模塊
  [root@localhost module_kernel]# insmod my_module.ko
  insmod: error inserting 'my_module.ko': -1 File exists
  [root@localhost module_kernel]# rmmod  my_module

二、出錯原因解決方法
  在插入模塊時常遇到的錯誤:
  [root@panlimin module_study]# insmod my_module.ko
  insmod: error inserting 'my_module.ko': -1 Invalid module format
  dmesg查看內(nèi)核報錯消息:
  [root@panlimin module_study]# dmesg
  my_module: no symbol version for module_layout
  [root@panlimin module_study]#

  一般出這個錯在make時會有類似這樣的警告:
  WARNING: Symbol version dump /root/study/kernel/linux-2.6.34/Module.symvers
           is missing; modules will have no dependencies and modversions.

  這是應該Linux內(nèi)核版本依賴出現(xiàn)了問題,這種情況一般出現(xiàn)在自行編譯內(nèi)核后沒有鏈接到正確的內(nèi)核源碼目錄樹情況,或者
  內(nèi)核目錄樹頂層的Module.symvers文件丟失。因為模塊代碼必須針對要鏈接的內(nèi)核版本重新編譯。
  如果沒有此警告,但在insmod時還是報此錯誤,就需要查看Module.symvers文件是否正確,比如這個文件可能是0字節(jié),
  Module.symvers在編譯內(nèi)核時會生成,如果發(fā)行版本在/lib/module/目錄下對應的內(nèi)核目錄樹中會有,此時只要確保該文件正確
  再重新make,insmod應該就沒問題了。

  除了insmod可以將模塊插入內(nèi)核外,modprobe也可以,它們的區(qū)別在于后者會考慮要插入的模塊是否引用了一些當前內(nèi)核不存在的符號,
  如果有這類引用,modprobe會在查找相應模塊并嘗試插入到內(nèi)核。所以有時使用insmod插入無效時還可以使用modprobe.

  如果由于模塊依賴導致符號表出現(xiàn)問題,比如,~/.viminfo被破壞,甚至無法加載網(wǎng)絡接口等,可以在/lib/module/對應的內(nèi)核目錄下
  執(zhí)行depmod -a重新生成正確的符號表,執(zhí)行過程需要點時間。


*博客內(nèi)容為網(wǎng)友個人發(fā)布,僅代表博主個人觀點,如有侵權請聯(lián)系工作人員刪除。



關鍵詞:

相關推薦

技術專區(qū)

關閉