通常情況下,一個模塊只使用內核導出的符號,自己不導出符號。但是如果一個模塊需要提供全局變量或函數給另外的模塊使用,那么就需要將這些符號導出。
這在一個驅動調用另一個驅動代碼時比較常見,這樣模塊和模塊之間就形成了依賴關系,使用導出符號的模塊將會依賴于導出符號的模塊。
舉個具體的例子,下面是兩個C文件,vser.c
調用了dep.c
中的變量和函數:
vser.c
#include < linux/init.h >
#include < linux/kernel.h >
#include < linux/module.h >
extern int expval;
extern void expfun(void);
static int __init vser_init(void)
{
printk("vser_init");
printk("expval:%dn", expval);
expfun();
return 0;
}
static void __exit vser_exit(void)
{
printk("vser_exitn");
}
module_init(vser_init);
module_exit(vser_exit);
dep.c
#include < linux/kernel.h >
#include < linux/module.h >
static int expval = 5;
EXPORT_SYMBOL(expval);
static void expfun(void)
{
printk("expfun");
}EXPORT_SYMBOL_GPL(expfun);
Makefile關鍵處:
obj-m := vser.o
obj-m += dep.o
上述代碼中,dep.c定義了一個變量expval
和一個函數expfun
,并分別用EXPORT_SYMBOL
和EXPORT_SYMBOL_GPL
導出。而vser.c
里則調用了dep.c
的變量和函數,編譯安裝后:
# modprobe vser
# dmesg
[58278.204677] vser_init
[58278.204683] expval:5
[58287.206464] expfun
從輸出信息中可以看到,vser.c
正確引用到了dep.c
的變量和函數。
這里有三點重要說明:
- 如果使用
insmod
命令加載模塊,則必須先加載dep模塊,再加載vser模塊 。
因為vser模塊用到了dep模塊的東西。從這里可以看出,modprobe
命令優于insmod
命令的地方在于其可以自動加載被依賴的模塊。而這又要歸功于depmod
命令,depmod
命令會生成模塊的依賴信息,保存在/lib/modules/5.10.111-64-generic/modules.dep
文件中。其中,5.10.111-64-generic是內核源碼版本。查看該文件可以發現vser模塊所依賴的模塊。
# cat /lib/modules/5.10.111-64-generic/modules.dep
......
extra/vser.ko: extra/dep.ko
extra/dep.ko:
- 兩個模塊存在依賴關系,如果分別編譯兩個模塊,會出現類似下面的警告信息,并且即便加載順序正確,加載也不會成功 :
WARNING: "expfun" [/home/ubuntu/driver/module/vser.ko] undefined!
WARNING: "expval" [/home/ubuntu/driver/module/vser.ko] undefined!
# sudo insmod dep.ko
# sudo insmod vser.ko
insmod:error inserting 'vser.ko': -1 Invalid parameters
這是因為在編譯vser
模塊時在內核的符號表中找不到expval
和expfun
的項,而vser
模塊又完全不知道dep
模塊的存在。
解決這個問題的方法是將兩個模塊放在一起編譯,或者將dep模塊放在內核源碼中,先在內核源碼下編譯完所有的模塊,再編譯vser模塊。
- 卸載模塊時要先卸載vser模塊,再卸載dep模塊,否則會因為dep模塊被vser模塊使用而不能卸載 。
內核將會創建模塊依賴關系的鏈接,只有當依賴于這個模塊的鏈表為空時,模塊才能被卸載.
-
模塊
+關注
關注
7文章
2670瀏覽量
47340 -
內核
+關注
關注
3文章
1363瀏覽量
40228 -
Linux
+關注
關注
87文章
11229瀏覽量
208926
發布評論請先 登錄
相關推薦
評論