歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux技術 >> Linux驅動開發——EXPORT_SYMBOL的使用

Linux驅動開發——EXPORT_SYMBOL的使用

日期:2017/3/3 12:40:13   编辑:Linux技術

編寫C程序時,如果需要使用某個外部的函數,通常的做法是 #include 包含該函數原型(prototype)的頭文件,然後在程序中進行調用。經過編譯鏈接後,程序就能順利調用該函數。但是對於內核模塊來說,這種方法並不適用,因此Linux內核提供了一種機制——內核模塊符號表機制。即使用 EXPORT_SYMBOL 標簽將模塊中的函數對整個內核公開,因此導出的函數不用修改內核代碼就可以被其他內核模塊所調用。

也就是說,使用 EXPORT_SYMBOL 可以將一個函數以符號的方式導出給其他模塊使用。下面以一個簡單的例子來說明如何使用 EXPORT_SYMBOL。 我們以導出符號 test_add 為例,在適當的位置創建 add.c 和 Makefile 文件,內容如下:

【add.c】

[code]#include <linux/module.h>

int test_add(int x, int y)
{
    return x+y;
}

EXPORT_SYMBOL(test_add);

MODULE_LICENSE("Dual BSD/GPL");
【Makefile】

[code]obj-m += add.o

KERN_VER := $(shell uname -r)
KERN_DIR  = /lib/modules/$(KERN_VER)/build

modules:
    $(MAKE) -C $(KERN_DIR) M=`pwd` modules
clean:
    $(MAKE) -C $(KERN_DIR) M=`pwd` modules clean
執行 make 命令後,生成 add.ko,執行命令 insmod add.ko 加載模塊。

確認 add 模塊加載成功:

[code]命令:
    cat /proc/modules | grep add
輸出:
    add 12465 0 - Live 0xf88f9000 (O)
確認 test_add 符號導出成功:

[code]命令:
    cat /proc/kallsyms | grep test_add
輸出:
    f88fa024 r __ksymtab_test_add   [add]
    f88fa030 r __kstrtab_test_add   [add]
    f88fa02c r __kcrctab_test_add   [add]
    f88f9000 T test_add [add]
接下來,在適當的位置創建 test.c 和 Makefile 文件進行測試,內容如下:

【test.c】

[code]#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>

/* 導出的符號可以被其他模塊使用,不過使用之前一定要聲明一下 */
int test_add(int x, int y);

static int __init test_init(void)
{
    printk(KERN_ALERT "test_init\n");
    printk(KERN_ALERT "%d\n", test_add(12, 13));
    return 0;
}

static void __exit test_exit(void)
{
    printk(KERN_ALERT "test_exit\n");
}

module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("Dual BSD/GPL");
【Makefile】

[code]obj-m += test.o

KERN_VER := $(shell uname -r)
KERN_DIR  = /lib/modules/$(KERN_VER)/build

modules:
    $(MAKE) -C $(KERN_DIR) M=`pwd` modules
clean:
    $(MAKE) -C $(KERN_DIR) M=`pwd` modules clean
執行 make 命令,發現如下警告:

[code]WARNING: "test_add" [/home/walle/workspace/export_symbol/test/test.ko] undefined!
如果我們忽略警告,直接執行 insmod test.ko,發現模塊加載失敗!

[code][806556.012242] test: no symbol version for test_add
[806556.012258] test: Unknown symbol test_add (err -22)
所以我們必須處理這個警告,而出現這樣警告的原因是 test 模塊不知道 test_add 的符號信息,解決辦法有兩個:

① 把 add 模塊的 Module.symvers 放到 test 模塊所在目錄下,重新編譯 test 模塊,test_add 的符號信息就會鏈接進去。

② 在 test 模塊的 Makefile 中使用 KBUILD_EXTRA_SYMBOLS 指定 add 模塊的 Module.symvers。

[code]KBUILD_EXTRA_SYMBOLS = /home/walle/workspace/export_symbol/add/Module.symvers

重新 make ,再次執行 insmod test.ko 加載模塊。

[code][806582.562028] test_init
[806582.562074] 25

可以看到,test 模塊已經成功調用 add 模塊的 test_add 函數了!(輸出結果25)

另外,也可以使用 EXPORT_SYMBOL_GPL 進行符號導出,但只適用於包含GPL許可權的模塊。(它們定義在 include/linux/export.h)

Copyright © Linux教程網 All Rights Reserved