linux模塊編寫

1、linux模塊化機制簡介linux

      模塊化的優點: linux內核是單內核結構,因爲全部內容都集成在一塊兒,效率很高,但可擴展性和可維護性相對較差,模塊機制彌補這一缺陷。shell

      Linux模塊能夠經過靜態或動態的方法加載到內核空間,靜態加載是指在內核啓動過程當中加載;動態加載是指在內核運行的過程當中隨時加載。一個模塊被加載到內核中時,就成爲內核代碼的一部分。模塊加載入系統時,系統修改內核中的符號表,將新加載的模塊提供的資源和符號添加到內核符號表中,以便模塊間的通訊。ubuntu

     從代碼的特徵上來看,模塊就是能夠完成一個獨立功能的一組函數的集合,但以特殊的方法來編譯,從而使之能夠在須要時隨時安裝,在不須要時隨時卸載。它們擴展了操做系統內核功能卻不須要從新編譯內核、啓動系統。centos

     

      Linux 內核模塊主要由如下幾個部分組成: 數據結構

      模塊加載函數(必須):當經過insmod命令加載內核模塊時,模塊的加載函數會自動被內核執行,完成本模塊相關初始化工做;
      模塊卸載函數(必須):當經過rmmod命令卸載模塊時,模塊的卸載函數會自動被內核執行,完成與模塊加載函數相反的功能;
      模塊許可證聲明(必須):模塊許可證(LICENCE)聲明描述內核模塊的許可權限,若是不聲明LICENCE,模塊被加載時將收到內核被污染的警告。大多數        模塊化

      模塊參數(可選):模塊參數是模塊被加載的時候能夠被傳遞給他的值,它自己對應模塊內部的全局變量;函數

      模塊導出符號(可選):內核模塊能夠導出符號(symbol,對應於函數或變量),這樣其餘模塊可使用本模塊中的變量或函數;
      模塊做者等信息聲明(可選)。ui

2、模塊的內核描述this

      每個內核模塊在內核中都對應一個數據結構module,全部的模塊經過一個鏈表維護spa

      在線查看內核源碼:https://elixir.bootlin.com

     

v2.6.28內核
include/linux/module.h

struct
module { enum module_state state; //模塊狀態,枚舉類型的變量,可取的值爲MODULE_STATE_LIVE、MODULE_STATE_COMING、MODULE_STATE_GOING,分爲當前正常使用中(存活狀態)、模塊當前正在被加載和模塊當前正在被卸載三種狀態。 /* Member of list of modules */ struct list_head list; //全部的模塊構成雙鏈表,包頭爲全局變量modules /* Unique handle for this module */ char name[MODULE_NAME_LEN]; //模塊名稱,通常不包含.ko /* Sysfs stuff. */ struct module_kobject mkobj; struct module_attribute *modinfo_attrs; const char *version; const char *srcversion; struct kobject *holders_dir; /* Exported symbols */ const struct kernel_symbol *syms; const unsigned long *crcs; unsigned int num_syms; /* GPL-only exported symbols. */ unsigned int num_gpl_syms; const struct kernel_symbol *gpl_syms; const unsigned long *gpl_crcs; #ifdef CONFIG_UNUSED_SYMBOLS /* unused exported symbols. */ const struct kernel_symbol *unused_syms; const unsigned long *unused_crcs; unsigned int num_unused_syms; /* GPL-only, unused exported symbols. */ unsigned int num_unused_gpl_syms; const struct kernel_symbol *unused_gpl_syms; const unsigned long *unused_gpl_crcs; #endif /* symbols that will be GPL-only in the near future. */ const struct kernel_symbol *gpl_future_syms; const unsigned long *gpl_future_crcs; unsigned int num_gpl_future_syms; /* Exception table */ unsigned int num_exentries; struct exception_table_entry *extable; /* Startup function. */ int (*init)(void); //模塊初始化函數指針 /* If this is non-NULL, vfree after init() returns */ void *module_init; //若是該函數不爲空,則init結束後就能夠調用進行適當釋放 /* Here is the actual code + data, vfree'd on unload. */ void *module_core; /* Here are the sizes of the init and core sections */ unsigned int init_size, core_size; /* The size of the executable code in each section. */ unsigned int init_text_size, core_text_size; /* The handle returned from unwind_add_table. */ void *unwind_info; /* Arch-specific module values */ struct mod_arch_specific arch; unsigned int taints; /* same bits as kernel:tainted */ #ifdef CONFIG_GENERIC_BUG /* Support for BUG */ unsigned num_bugs; struct list_head bug_list; struct bug_entry *bug_table; #endif #ifdef CONFIG_KALLSYMS /* We keep the symbol and string tables for kallsyms. */ Elf_Sym *symtab; unsigned int num_symtab; char *strtab; /* Section attributes */ struct module_sect_attrs *sect_attrs; /* Notes attributes */ struct module_notes_attrs *notes_attrs; #endif /* Per-cpu data. */ void *percpu; /* The command line arguments (may be mangled). People like keeping pointers to this stuff */ char *args; #ifdef CONFIG_MARKERS struct marker *markers; unsigned int num_markers; #endif #ifdef CONFIG_TRACEPOINTS struct tracepoint *tracepoints; unsigned int num_tracepoints; #endif #ifdef CONFIG_MODULE_UNLOAD /* What modules depend on me? */ struct list_head modules_which_use_me; /* Who is waiting for us to be unloaded */ struct task_struct *waiter; /* Destruction function. */ void (*exit)(void); /* Reference counts */ struct module_ref ref[NR_CPUS]; #endif };

 

3、實驗

     hello模塊

      ubuntu 請安裝源代碼 

sudo apt-get install linux-source

 

     centos安裝

yum install kernel*

     hello.c

    

#include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h>

static int __init init_hello(void) { printk(KERN_ALERT "my first module test,output \"hello!\"\n"); return 0; } static void __exit exit_hello(void) { printk(KERN_DEBUG "bye bye test module!\n"); } module_init(init_hello); module_exit(exit_hello); MODULE_LICENSE("GPL"); MODULE_AUTHOR("xiaoan"); MODULE_VERSION("v0.1"); MODULE_DESCRIPTION("TEST FOR MODULE");

Makefile

  

obj-m := hello.o KERNELBUILD :=/lib/modules/$(shell uname -r)/build default: make -C $(KERNELBUILD) M=$(shell pwd) modules

 

執行make 便可

驗證:

    

$ inmod ./hello.ko$ dmesg...  [ 2502.490509] my first module test,output "hello!"$ rmmod heelo.ko$ dmesg...   [ 2568.969806] bye bye test module!
相關文章
相關標籤/搜索