Linux核心模組編程簡介

來源:互聯網
上載者:User

主題: linux核心模組的程式結構--模組載入函數(必須),模組卸載函數(必須),模組許可證聲明(必須),模組參數(可選),模組匯出符號(可選),模組作者的等資訊聲明(可選)

一個linux核心模組主要由以下幾個部分組成。
1、模組載入函數"用module_init()來指定"(必須)
   當通過insmod和modprobe命令載入核心模組時,模組的載入函數會自動被核心執行,完成本模組的相關初始化工作。
linux模組載入函數一般以 __init表示聲明。典型聲明如下::
static int __init  initialization_function(void)
{
       /*初始化代碼*/
}
module_init(initialization_function);
    模組載入函數必須使用module_init(函數名)的形式被指定。它返回整型值,若初始化成功,應返回0,而初始化失敗時,應返回錯誤編碼。在linux核心中,錯誤編碼是一個負值,在<linux/errno.h>中定義,包括-ENODEV、-ENOMEM之類的符號值。返回相應的錯誤編碼是種非常好的習慣,只有這樣,應用程式才能利用perror等方法把他們轉換成有意義的錯誤資訊字串。
    在2.6核心中,可以使用“request_module(const char *fmt,...)函數”載入核心模組(注意:前面載入模組都是通過insmod和modprobe來實現的),驅動開發人員可以通過調用::
request_module(module_name);

request_module("char-major-%d-%d",MAJOR(dev),MINOR(dev));
來載入其他核心模組。
   在linux核心中,所有表示為__init的函數在串連的時候放在.init.text這個區段內,此外,所有的__init函數在段.initcall.init中還儲存了一份函數指標,在初始化時,核心會通過這些指標調用這些__init函數,並在初始化完成後釋放init區段(.init.text,.initcall.init等)。
////////////////////////////////////////////////////////////////////
2、模組卸載函數"用module_exit()來指定"(必須)
   當通過rmmod和modprobe -r命令卸載核心模組時,模組的卸載函數會自動被核心執行,完成與模組載入函數相反的功能。
   linux核心模組於在函數一般以__exit表示說明,典型的模組卸載函數的形式如下::
static void __exit  cleanup_function(void)
{
         /*釋放代碼*/
}
module_exit(cleanup_function);
   模組卸載函數在模組卸載的時候執行,不返回任何值,必須以"module_exit(函數名)"的形式來指定。
通常來說,模組卸載函數要完成與模組載入函數相反的功能,如下::
1>若模組載入函數註冊了XXX,則模組卸載函數應該登出XXX;
2>若模組記載函數的動態申請了記憶體,則模組函數應該釋放該該記憶體。
3>若模組載入函數申請了硬體資源(中斷,DMA通道、I/O連接埠和I/O記憶體等)的佔用,則模組卸載函數應該釋放這些硬體資源。
4>模組載入函數一般用來開啟硬體,模組卸載函數一般要關閉硬體。

和__init一樣,__exit也可以使用對應函數在運行完成後自動回收記憶體。實際上,__init和__exit都是宏,
分別定義為::
#define __init __attribute__((__section__(".init.text")))

#ifdef MODULE
#define __exit __attribute__((__section__(".exit.text")))
#else
#define __exit    / __attribute__used____attribute((__section__(".exit.text")))
#endif
/////////////////////////////////////////////////////////////////////
3、模組許可證聲明"MODULE_LICENSE("Daul BSD/GPL")"(必須)
   模組許可證(LICENSE)聲明描述核心模組的許可許可權,如果不聲明LICENSE,模組被載入時,將收到核心被汙染(kernel tainted)的警告。
   在linux2.6核心中,可接受的LICENSE包括"GPL"、"GPL v2"、"GPL and additional rights"、"Dual BSD/GPL"、"Dual MPL/GPL"和"Proprietary"

大多數情況下,核心模組應遵循GPL相容許可權。linux2.6核心模組中最常見的是以MODULE_LICENSE("Dual BSD/GPL")語句聲明模組採用BSD/GPL雙LICENSE.

//////////////////////////////////////////////////////////////////////
4、模組參數(可選)
“模組參數”是“模組被載入的時候可以被傳遞給模組的值”,它本身對應模組內部的“全部變數”。
   我們可以使用"module_param(參數名,參數類型,讀/寫入權限)"為模組定義一個參數,例如::下列代碼定義了一個整型參數和一個字元指標參數。
static char *book_name="深入淺出linux裝置驅動";
static int num = 4000;
module_param(num,int,S_IRUGO);
module_param(book_name,charp,S_IRGUO);

在裝載核心模組時,使用者可以向核心模組傳遞參數,
形式為"sudo insmod/modprobe 模組名(例如linux.ko)   參數名=參數值",若果不傳遞,參數將使用模組內定義的預設值。

向核心模組傳遞參數時,參數的類型可以是byte(位元組),short(短整型),ushort(無符號短整型),int,uint(無符號int),long,ulong(無符號long)、charp(字元指標)、bool或invbool(布爾的反),在模組被編譯時間會將module_param中聲明的類型與變數定義的類型進行比較,判斷是否一致。

   模組被載入後,在/sys/module目錄下將出現以此模組名命名的目錄。當"參數讀/寫入權限"為0時,表示此“參數不存在sysfs檔案系統下對應的檔案節點”,如果此模組存在"參數讀/寫入權限"不為0的命令列參數,在此模組的目錄下將出現parameters目錄,包含一系列“以參數名命名的檔案節點”。同時,這些檔案的許可權就是通過傳入module_param()的"參數讀/寫入權限",而檔案的內容為參數的值。

   除此之外,模組也可以擁有參數數組,形式為"module_param_array(數組名,數群組類型,數組長,參數讀/寫入權限)",在2.6.0~2.6.10版本,需將數組常變數名賦給"數組長",從2.6.10版本開始,需將數組長變數的指標賦給"數組長",當不需要儲存實際輸入的數組元數個數時,可以設定"數組長"為NULL。
  
   運行insmod和modprobe命令時,應使用逗號分割輸入的數組元素。
例如::
#include<linux/init.h>
#include<linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
   
static char *book_name="Dissecting Linux Device Driber";
static int num=4000;

static int __init book_init(void)
{
    printk(KERN_INFO"book name :%s/n",book_name);
    printk(KERN_INFO"book num :%s/n",num);
    return 0;
}

static void __exit book_exit(void)
{
    printk(KERN_INFO"Book module exit/n");
}

module_init(book_init);
module_exit(book_exit);

module_param(num,int,S_IRUGO);
module_param(book_name,charp,S_IRUGO);

MODULE_AUTHOR("chenbaihu");
MODULE_VERSION("v1.0");
MODULE_DESCRIPTION("A simple Module for testing module params");
編譯該模組,Makefile為::
obj-m := module_param.o
kernel_path=/usr/src/kernels/2.6.29.6-217.2.16.fc11.i686.PAE 
//核心路徑
all:
    make -C $(kernel_path)  M=$(PWD) modules
clean:
    make -C $(kernel_path)  M=$(PWD) clean
然後,運行make命令,進行編譯.產生module_param.ko檔案.
載入該模組.
第一種方案::
    “sudo insmod module_param.ko”命令時,運行結果為::
book name :Dissecting Linux Device Driber
book num :4000
第二種方案::
   “sudo insmod module_param.ko num=5000”命令時,運行結果為::
book name :Dissecting Linux Device Driber
book num :5000   //參數傳入了。
進入/sys/module/module_param/下,輸入tree命令::
.
|-- holders
|-- initstate
|-- notes
|-- parameters
|   |-- book_name     //模組參數檔案
|   `-- num           //模組參數檔案
|-- refcnt
|-- sections
|   `-- __param
|-- srcversion
`-- version
//////////////////////////////////////////////////////////////////////
5、模組匯出符號(可選)
核心模組可以匯出符號(symbol,對應與函數或變數),這樣其他模組可以使用本模組中的變數和函數。

     linux2.6的"/proc/kallsyms"檔案對應這核心符號表,它記錄了符號以及符號符號所在的記憶體位址。
模組可以使用如下宏匯出符號到核心符號表::
    EXPORT_SYMBOL(符號名);
    EXPORT_SYMBOL_GPL(符合名);    //只是用於GPL許可權模組。
匯出的符合將可以被其他模組使用,使用前聲明以下既可以。

核心模組中的符號匯出(例子)::
#include<linux/init.h>
#include<linux/module.h>
MODULE_LICENSE("Daul BSD/GPL");

int add_integar(int a,int b)
{
    return a+b;
}
int sub_integer(int a,int b)
{
    return a-b;
}

EXPORT_SYMBOL(add_integar);    //匯出函數
EXPORT_SYMBOL(sub_integer);    //匯出函數
編譯後,sudo insmod export_symbol.ko將該模組加入核心。
從"/proc/kallsyms"中可以找到add_integae/sub_integer相關資訊。
使用"cat /proc/kallsyms|grep integar"命令,就可以看到下面的結果::
f99f8048 r __ksymtab_add_integar    [export_symbol]
f99f805c r __kstrtab_add_integar    [export_symbol]
f99f8000 T add_integar    [export_symbol]

6、模組作者等資訊(可選)
MODULE_AUTOR("作者資訊");
MODULE_DESCRIPTION("模組描述資訊");
MODULE_VERSION("版本資訊");
MODULE_ALIAS("別名資訊");
MODULE_DEVICE_TABLE("裝置表資訊");
對於USB,PCI等裝置驅動,通常會建立一個MODULE_DEVICE_TABLE,表示驅動所支援的裝置列表。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.