国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
linux內(nèi)核模塊編程

linux內(nèi)核模塊編程

文章分類(lèi):JavaEye

主題: linux內(nèi)核模塊的程序結(jié)構(gòu)--模塊加載函數(shù)(必須),模塊卸載函數(shù)(必須),模塊許可證聲明(必須),模塊參數(shù)(可選),模塊導(dǎo)出符號(hào)(可選),模塊作者的等信息聲明(可選)

一個(gè)linux內(nèi)核模塊主要由以下幾個(gè)部分組成。
1、模塊加載函數(shù)"用module_init()來(lái)指定"(必須)
   當(dāng)通過(guò)insmod和modprobe命令加載內(nèi)核模塊時(shí),模塊的加載函數(shù)會(huì)自動(dòng)被內(nèi)核執(zhí)行,完成本模塊的相關(guān)初始化工作。
linux模塊加載函數(shù)一般以 __init表示聲明。典型聲明如下::
static int __init  initialization_function(void)
{
       /*初始化代碼*/
}
module_init(initialization_function);
    模塊加載函數(shù)必須使用module_init(函數(shù)名)的形式被指定。它返回整型值,若初始化成功,應(yīng)返回0,而初始化失敗時(shí),應(yīng)返回錯(cuò)誤編碼。在linux內(nèi)核中,錯(cuò)誤編碼是一個(gè)負(fù)值,在<linux/errno.h>中定義,包括-ENODEV、-ENOMEM之類(lèi)的符號(hào)值。返回相應(yīng)的錯(cuò)誤編碼是種非常好的習(xí)慣,只有這樣,應(yīng)用程序才能利用perror等方法把他們轉(zhuǎn)換成有意義的錯(cuò)誤信息字符串。
    在2.6內(nèi)核中,可以使用“request_module(const char *fmt,...)函數(shù)”加載內(nèi)核模塊(注意:前面加載模塊都是通過(guò)insmod和modprobe來(lái)實(shí)現(xiàn)的),驅(qū)動(dòng)開(kāi)發(fā)人員可以通過(guò)調(diào)用::
request_module(module_name);

request_module("char-major-%d-%d",MAJOR(dev),MINOR(dev));
來(lái)加載其他內(nèi)核模塊。
   在linux內(nèi)核中,所有表示為_(kāi)_init的函數(shù)在連接的時(shí)候放在.init.text這個(gè)區(qū)段內(nèi),此外,所有的__init函數(shù)在段.initcall.init中還保存了一份函數(shù)指針,在初始化時(shí),內(nèi)核會(huì)通過(guò)這些指針調(diào)用這些__init函數(shù),并在初始化完成后釋放init區(qū)段(.init.text,.initcall.init等)。
////////////////////////////////////////////////////////////////////
2、模塊卸載函數(shù)"用module_exit()來(lái)指定"(必須)
   當(dāng)通過(guò)rmmod和modprobe -r命令卸載內(nèi)核模塊時(shí),模塊的卸載函數(shù)會(huì)自動(dòng)被內(nèi)核執(zhí)行,完成與模塊加載函數(shù)相反的功能。
   linux內(nèi)核模塊于在函數(shù)一般以__exit表示說(shuō)明,典型的模塊卸載函數(shù)的形式如下::
static void __exit  cleanup_function(void)
{
         /*釋放代碼*/
}
module_exit(cleanup_function);
   模塊卸載函數(shù)在模塊卸載的時(shí)候執(zhí)行,不返回任何值,必須以"module_exit(函數(shù)名)"的形式來(lái)指定。
通常來(lái)說(shuō),模塊卸載函數(shù)要完成與模塊加載函數(shù)相反的功能,如下::
1>若模塊加載函數(shù)注冊(cè)了XXX,則模塊卸載函數(shù)應(yīng)該注銷(xiāo)XXX;
2>若模塊記載函數(shù)的動(dòng)態(tài)申請(qǐng)了內(nèi)存,則模塊函數(shù)應(yīng)該釋放該該內(nèi)存。
3>若模塊加載函數(shù)申請(qǐng)了硬件資源(中斷,DMA通道、I/O端口和I/O內(nèi)存等)的占用,則模塊卸載函數(shù)應(yīng)該釋放這些硬件資源。
4>模塊加載函數(shù)一般用來(lái)開(kāi)啟硬件,模塊卸載函數(shù)一般要關(guān)閉硬件。

和__init一樣,__exit也可以使用對(duì)應(yīng)函數(shù)在運(yùn)行完成后自動(dòng)回收內(nèi)存。實(shí)際上,__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)聲明描述內(nèi)核模塊的許可權(quán)限,如果不聲明LICENSE,模塊被加載時(shí),將收到內(nèi)核被污染(kernel tainted)的警告。
   在linux2.6內(nèi)核中,可接受的LICENSE包括"GPL"、"GPL v2"、"GPL and additional rights"、"Dual BSD/GPL"、"Dual MPL/GPL"和"Proprietary"

大多數(shù)情況下,內(nèi)核模塊應(yīng)遵循GPL兼容許可權(quán)。linux2.6內(nèi)核模塊中最常見(jiàn)的是以MODULE_LICENSE("Dual BSD/GPL")語(yǔ)句聲明模塊采用BSD/GPL雙LICENSE.

//////////////////////////////////////////////////////////////////////
4、模塊參數(shù)(可選)
“模塊參數(shù)”是“模塊被加載的時(shí)候可以被傳遞給模塊的值”,它本身對(duì)應(yīng)模塊內(nèi)部的“全部變量”。
   我們可以使用"module_param(參數(shù)名,參數(shù)類(lèi)型,讀/寫(xiě)權(quán)限)"為模塊定義一個(gè)參數(shù),例如::下列代碼定義了一個(gè)整型參數(shù)和一個(gè)字符指針參數(shù)。
static char *book_name="深入淺出linux設(shè)備驅(qū)動(dòng)";
static int num = 4000;
module_param(num,int,S_IRUGO);
module_param(book_name,charp,S_IRGUO);

在裝載內(nèi)核模塊時(shí),用戶可以向內(nèi)核模塊傳遞參數(shù),
形式為"sudo insmod/modprobe 模塊名(例如linux.ko)   參數(shù)名=參數(shù)值",若果不傳遞,參數(shù)將使用模塊內(nèi)定義的默認(rèn)值。

向內(nèi)核模塊傳遞參數(shù)時(shí),參數(shù)的類(lèi)型可以是byte(字節(jié)),short(短整型),ushort(無(wú)符號(hào)短整型),int,uint(無(wú)符號(hào)int),long,ulong(無(wú)符號(hào)long)、charp(字符指針)、bool或invbool(布爾的反),在模塊被編譯時(shí)會(huì)將module_param中聲明的類(lèi)型與變量定義的類(lèi)型進(jìn)行比較,判斷是否一致。

   模塊被加載后,在/sys/module目錄下將出現(xiàn)以此模塊名命名的目錄。當(dāng)"參數(shù)讀/寫(xiě)權(quán)限"為0時(shí),表示此“參數(shù)不存在sysfs文件系統(tǒng)下對(duì)應(yīng)的文件節(jié)點(diǎn)”,如果此模塊存在"參數(shù)讀/寫(xiě)權(quán)限"不為0的命令行參數(shù),在此模塊的目錄下將出現(xiàn)parameters目錄,包含一系列“以參數(shù)名命名的文件節(jié)點(diǎn)”。同時(shí),這些文件的權(quán)限就是通過(guò)傳入module_param()的"參數(shù)讀/寫(xiě)權(quán)限",而文件的內(nèi)容為參數(shù)的值。

   除此之外,模塊也可以擁有參數(shù)數(shù)組,形式為"module_param_array(數(shù)組名,數(shù)組類(lèi)型,數(shù)組長(zhǎng),參數(shù)讀/寫(xiě)權(quán)限)",在2.6.0~2.6.10版本,需將數(shù)組常變量名賦給"數(shù)組長(zhǎng)",從2.6.10版本開(kāi)始,需將數(shù)組長(zhǎng)變量的指針賦給"數(shù)組長(zhǎng)",當(dāng)不需要保存實(shí)際輸入的數(shù)組元數(shù)個(gè)數(shù)時(shí),可以設(shè)置"數(shù)組長(zhǎng)"為NULL。
  
   運(yùn)行insmod和modprobe命令時(shí),應(yīng)使用逗號(hào)分割輸入的數(shù)組元素。
例如::
#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 
//內(nèi)核路徑
all:
    make -C $(kernel_path)  M=$(PWD) modules
clean:
    make -C $(kernel_path)  M=$(PWD) clean
然后,運(yùn)行make命令,進(jìn)行編譯.生成module_param.ko文件.
加載該模塊.
第一種方案::
    “sudo insmod module_param.ko”命令時(shí),運(yùn)行結(jié)果為::
book name :Dissecting Linux Device Driber
book num :4000
第二種方案::
   “sudo insmod module_param.ko num=5000”命令時(shí),運(yùn)行結(jié)果為::
book name :Dissecting Linux Device Driber
book num :5000   //參數(shù)傳入了。
進(jìn)入/sys/module/module_param/下,輸入tree命令::
.
|-- holders
|-- initstate
|-- notes
|-- parameters
|   |-- book_name     //模塊參數(shù)文件
|   `-- num           //模塊參數(shù)文件
|-- refcnt
|-- sections
|   `-- __param
|-- srcversion
`-- version
//////////////////////////////////////////////////////////////////////
5、模塊導(dǎo)出符號(hào)(可選)
內(nèi)核模塊可以導(dǎo)出符號(hào)(symbol,對(duì)應(yīng)與函數(shù)或變量),這樣其他模塊可以使用本模塊中的變量和函數(shù)。

     linux2.6的"/proc/kallsyms"文件對(duì)應(yīng)這內(nèi)核符號(hào)表,它記錄了符號(hào)以及符號(hào)符號(hào)所在的內(nèi)存地址。
模塊可以使用如下宏導(dǎo)出符號(hào)到內(nèi)核符號(hào)表::
    EXPORT_SYMBOL(符號(hào)名);
    EXPORT_SYMBOL_GPL(符合名);    //只是用于GPL許可權(quán)模塊。
導(dǎo)出的符合將可以被其他模塊使用,使用前聲明以下既可以。

內(nèi)核模塊中的符號(hào)導(dǎo)出(例子)::
#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);    //導(dǎo)出函數(shù)
EXPORT_SYMBOL(sub_integer);    //導(dǎo)出函數(shù)
編譯后,sudo insmod export_symbol.ko將該模塊加入內(nèi)核。
從"/proc/kallsyms"中可以找到add_integae\sub_integer相關(guān)信息。
使用"cat /proc/kallsyms|grep integar"命令,就可以看到下面的結(jié)果::
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("設(shè)備表信息");
對(duì)于USB,PCI等設(shè)備驅(qū)動(dòng),通常會(huì)創(chuàng)建一個(gè)MODULE_DEVICE_TABLE,表示驅(qū)動(dòng)所支持的設(shè)備列表。
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
ldd3之模塊學(xué)習(xí)總結(jié)(頁(yè) 1) - 文檔專(zhuān)區(qū) - 無(wú)分類(lèi)文檔 - Linux論壇 - p...
linux模塊編程
增加自定義的內(nèi)核啟動(dòng)參數(shù)
linux設(shè)備驅(qū)動(dòng)歸納總結(jié)(二):模塊的相關(guān)基礎(chǔ)概念
Linux驅(qū)動(dòng)程序入門(mén)—Hello World - 藍(lán)博芯科
使用/proc文件系統(tǒng)來(lái)訪問(wèn)Linux內(nèi)核(上)
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服