日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux 驱动开发之内核模块开发(四)—— 符号表的导出

發(fā)布時間:2023/12/9 linux 54 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux 驱动开发之内核模块开发(四)—— 符号表的导出 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

?Linux內(nèi)核頭文件提供了一個方便的方法用來管理符號的對模塊外部的可見性,因此減少了命名空間的污染(命名空間的名稱可能會與內(nèi)核其他地方定義的名稱沖突),并且適當信息隱藏。 如果你的模塊需要輸出符號給其他模塊使用,應當使用下面的宏定義:

EXPORT_SYMBOL(name);

EXPORT_SYMBOL_GPL(name);?? //只適用于包含GPL許可權(quán)的模塊;

? ? ?這兩個宏均用于將給定的符號導出到模塊外. _GPL版本的宏定義只能使符號對GPL許可的模塊可用。?符號必須在模塊文件的全局部分導出,不能在函數(shù)中導出,這是因為上述這兩個宏將被擴展成一個特殊用途的聲明,而該變量必須是全局的。這個變量存儲于模塊的一個特殊的可執(zhí)行部分(一個"ELF段" ),在裝載時,內(nèi)核通過這個段來尋找模塊導出的變量(感興趣的讀者可以看<linux/module.h>獲知更詳細的信息)。


一、宏定義EXPORT_SYMBOL分析

1、源碼

[cpp]?view plaincopy
  • <include/linux/moudule.h>??
  • ??
  • …….??
  • ??
  • #ifndef?MODULE_SYMBOL_PREFIX??
  • #define?MODULE_SYMBOL_PREFIX?""??
  • #endif??
  • ??
  • …….??
  • ??
  • struct?kernel_symbol???????//內(nèi)核符號結(jié)構(gòu)??
  • {??
  • ???????unsignedlong?value;??//該符號在內(nèi)存地址中的地址??
  • ???????constchar?*name;?????//該符號的名稱??
  • ??
  • };??
  • ??
  • ……??
  • ??
  • #define?__EXPORT_SYMBOL(sym,sec)?????????????????????????????????\??
  • ???????externtypeof(sym)?sym;????????????????????????????????????????????????????????\??
  • ???????__CRC_SYMBOL(sym,sec)????????????????????????????????????????????\??
  • ???????staticconst?char?__kstrtab_##sym[]?????????????????????????????????\??
  • ???????__attribute__((section(“__ksymtab_strings”),aligned(1)))???\??
  • ???????=MODULE_SYMBOL_PREFIX#sym;??????????????????????\??
  • ???????staticconst?struct?kernel_symbol?__ksymtab_##sym?????????\??
  • ???????__used??????????????????????????????????????????????????????????????????????????\??
  • ???????__attribute__((section(“__ksymatab”sec),unused))???????????????????\??
  • ???????={(unsignedlong)&sym,_kstrab_#sym}???
  • ??
  • #define????EXPORT_SYMBOL(sym)???????????????????\??
  • ??????????????__EXPOTR_SYMBOL(sym,””)??
  • ??
  • #define????EXPORT_SYMBOL_GPL(sym)???????????\??
  • ??????????????__EXPOTR_SYMBOL(sym,”_gpl”)??
  • ??
  • #define????EXPORT_SYMBOL(sym)???????????????????\??
  • ??????????????__EXPOTR_SYMBOL(sym,”_gpl_future”)??

  • 在分析前,先了解如下相關(guān)知識:

    1)#運算符,##運算符

    ? ? ?通常在宏定義中使用#來創(chuàng)建字符串 #abc就表示字符串”abc”等。

    ? ? ##運算符稱為預處理器的粘合劑,用來替換粘合兩個不同的符號,

    如:#define xName (n) ?x##n

    則xName(4) ?則變?yōu)閤4


    2)gcc的 __attribute__ 屬性:

    ? ? ?__attribute__((section(“section_name”)))的作用是將指定的函數(shù)或變量放入到名為”section_name”的段中

    ? ? __attribute__屬性添加可以在函數(shù)或變量定義的時候直接加入在定義語句中。

    如:

    int myvar__attribute__((section("mydata"))) = 0;

    表示定義了整形變量myvar=0;并且將該變量存放到名為”mydata”的section中

    關(guān)于gcc_attribute詳解可以參考:http://blog.sina.com.cn/s/blog_661314940100qujt.html


    2、EXPORT_SYMBOL的作用是什么?

    ? ? ? ?EXPORT_SYMBOL標簽內(nèi)定義的函數(shù)或者符號對全部內(nèi)核代碼公開,不用修改內(nèi)核代碼就可以在您的內(nèi)核模塊中直接調(diào)用,即使用EXPORT_SYMBOL可以將一個函數(shù)以符號的方式導出給其他模塊使用。

    ? ? ? ?這里要和System.map做一下對比:System.map 中的是連接時的函數(shù)地址。連接完成以后,在2.6內(nèi)核運行過程中,是不知道哪個符號在哪個地址的。

    ? ? ? ?EXPORT_SYMBOL的符號,是把這些符號和對應的地址保存起來,在內(nèi)核運行的過程中,可以找到這些符號對應的地址。而模塊在加載過程中,其本質(zhì)就是能動態(tài)連接到內(nèi)核,如果在模塊中引用了內(nèi)核或其它模塊的符號,就要EXPORT_SYMBOL這些符號,這樣才能找到對應的地址連接。


    二、 EXPORT_SYMBOL使用方法

    第一、在模塊函數(shù)定義之后使用EXPORT_SYMBOL(函數(shù)名)

    第二、在調(diào)用該函數(shù)的模塊中使用extern對之聲明

    第三、首先加載定義該函數(shù)的模塊,再加載調(diào)用該函數(shù)的模塊

    要調(diào)用別的模塊實現(xiàn)的函數(shù)接口和全局變量,就要導出符號?/usr/src/linux-headers-2.6.32-33-generic/Module.symvers

    A B
    static?int?num?=10; static?void?show(void) { printk("%d??\n",num); } EXPORT_SYMBOL(show); extern?void?show(void);

    函數(shù)A先將show() 函數(shù)導出,函數(shù)B 使用extern 對其聲明,要注意:

    a -- 編譯a模塊后,要將?Module.symvers?拷貝到b模塊下

    b -- 然后才能編譯b模塊

    c -- 加載:先加載a模塊,再加載b模塊

    d -- 卸載:先卸載b模塊,再卸載a模塊


    三、示例
    代碼a ,hello.c [cpp]?view plaincopy
  • #include?<linux/module.h>??
  • ??
  • static?int?num?=10;??
  • static?void?show(void)??
  • {??
  • ????printk("show(),num?=?%d\n",num);??
  • }??
  • static?int?hello_init(void)??
  • {??
  • ????printk("hello_init");??
  • ????return?0;??
  • }??
  • static?void?hello_exit(void)??
  • {??
  • ????printk("hello_exit?\n");??
  • }??
  • EXPORT_SYMBOL(show);??
  • MODULE_LICENSE("GPL");??
  • module_init(hello_init);??
  • module_exit(hello_exit);??

  • 代碼b show.c [cpp]?view plaincopy
  • #include?<linux/module.h>??
  • ??
  • extern?void?show(void);??
  • ??
  • static?int?show_init(void)??
  • {??
  • ????printk("show_init");??
  • ????show();??
  • ????return?0;??
  • }??
  • static?void?show_exit(void)??
  • {??
  • ????printk("show_exit?\n");??
  • }??
  • ??
  • MODULE_LICENSE("GPL");??
  • ??
  • module_init(show_init);??
  • module_exit(show_exit);<strong>??
  • </strong>??

  • 編譯后加載模塊,卸載模塊,可以用?dmesg?查看內(nèi)核打印信息。

    總結(jié)

    以上是生活随笔為你收集整理的Linux 驱动开发之内核模块开发(四)—— 符号表的导出的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。