[解決済み] 他のモジュールで定義されたシンボルに対して、insmod が "Unknown symbol in module" で失敗する。
質問
私はUbuntuで仕事をしています。私は、互いの機能を使用する2つのカーネルモジュールを作成しようとしています。私の問題は、私はモジュールを適切にコンパイルしましたが、それらのうちの1つのためにシンボルが解決されていないことです。
簡単に説明するために、これらのモジュールの名前を
m1
と
m2
.
m2 は関数をエクスポートしています。
void func_m2(void)
. また
m1
がこの関数を呼び出しています。どちらのモジュールも正しくコンパイルされます。
すべてのコンパイルが完了したら、最初に
m2
モジュール(これは
func_m2
関数)の後に
m1
モジュールになります。では、作ってみましょう。
volodymyr@sv1:~/development/kmodules/m2$ sudo insmod ./m2.ko
では、次のようにロードします。
m1
を使おうとしているモジュールは
func_m2
:
volodymyr@sv1:~/development/kmodules/m1$ sudo insmod ./m1.ko
insmod: error inserting './m1.ko': -1 Unknown symbol in module
以下は、ログに表示される内容です。
volodymyr@sv1:~/development/kmodules/m1$ dmesg | tail
[ 3938.166616] Loading m2 module ...
[ 3963.078055] m1: no symbol version for func_m2
[ 3963.078059] m1: Unknown symbol func_m2
ということで、どうやら、シンボルへの参照は
func_m2
が解決されない。面白いですね。シンボル・テーブルに存在するかどうか調べてみましょう。
volodymyr@sv1:~/development/kmodules$ cat /proc/kallsyms | grep 'func_m2'
ffffffffa00530d0 r __ksymtab_func_m2 [m2]
ffffffffa00530e8 r __kstrtab_func_m2 [m2]
ffffffffa00530e0 r __kcrctab_func_m2 [m2]
ffffffffa0053000 T func_m2 [m2]
000000004edd543f a __crc_func_m2 [m2]
ご覧の通り
func_m2
は実際にシンボルテーブルに存在する。では、なぜ
m1
を読み込むことができないのですか?
カーネルとLinuxソースのLinuxヘッダーはきちんとインストールしました。カーネルには何も手を加えておらず、バージョンは 2.6.31-16-generic です (x64 を使用しています)。
さて、全体像をお見せするために、このテストに使用したソースコードと Makefile を以下に掲載します。
m1
と
m2
モジュールになります。
m1
モジュールになります。
m1.c:
#include <linux/module.h>
#include <linux/kernel.h>
extern void func_m2(void);
int hello_start(void)
{
printk(KERN_INFO "Loading m1 module ...\n");
func_m2();
return 0;
}
void hello_end(void)
{
printk(KERN_INFO "Unloading m1 ...\n");
}
module_init(hello_start);
module_exit(hello_end);
MODULE_LICENSE("GPL");
メイクファイルです。
obj-m := m1.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
m2
モジュールになります。
m2.c:
#include <linux/module.h>
#include <linux/kernel.h>
int hello_start(void)
{
printk(KERN_INFO "Loading m2 module ...\n");
return 0;
}
void hello_end(void)
{
printk(KERN_INFO "Unloading m2 ...\n");
}
void func_m2(void)
{
printk(KERN_INFO "This a function in m2\n");
}
module_init(hello_start);
module_exit(hello_end);
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(func_m2);
メイクファイルです。
obj-m := m2.o
export-objs := m2.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
基本的に私の質問は
なぜ
m1
が読み込まれるのですか?
どなたか回答していただけると助かります。
どのように解決するのですか?
以下は、あなたのコードで見つけたいくつかの問題点です。
(a). 初期化関数と終了関数は静的に宣言され、適切に識別されるべきです。例えば、m1.c -では
static int __init hello_start(void)
{
printk(KERN_INFO "Loading m1 module ...\n");
func_m2();
return 0;
}
static void __exit hello_end(void)
{
printk(KERN_INFO "Unloading m1 ...\n");
}
これをm2.cに繰り返す
(b). 同じ Makefile を使って、両方のモジュールを一緒にビルドしてください。m1.c 用の既存の Makefile の出力をよく見ると、func_m2() が未定義であることを示す警告が表示されていることでしょう。いずれにせよ、統合された Makefile は以下のようになるはずです。
SRCS = m1.c m2.c
OBJS = $(SRCS:.c=.o)
obj-m += $(OBJS)
EXTRA_CFLAGS = -O2
all:
$(MAKE) -C /lib/modules/`uname -r`/build M=$(PWD) modules
clean:
$(MAKE) -C /lib/modules/`uname -r`/build M=$(PWD) clean
$(RM) Module.markers modules.order
両方のモジュールがビルドされたら、'm1.ko' の insmod を実行する前に 'm2.ko' の insmod を実行します。dmesg で結果を確認します。
また、ここでは、m1.cとm2.cが同じディレクトリにあるものと仮定しています。異なるディレクトリにある場合でも、このテクニックは有効ですが、面倒なことになります。異なるディレクトリにある場合は、次のようにしてください。
少し調べてみたところ、モジュールを別々のディレクトリにビルドする方法がありました。私が使った例は、あなたが持っているものよりもずっとシンプルですが、おそらく適応可能でしょう。
というディレクトリに、次のようなファイルのマニフェストがあります。 エクスポートシンボル ...
$ ls -CFR
.:
include/ Makefile mod1/ mod2/
./include:
m2_func.h
./mod1:
Makefile module1.c
./mod2:
Makefile module2.c
m2_func.hは、次のように表示されます。
#ifndef M2_FUNC_H
#define M2_FUNC_H
void m2_func(void);
#endif
トップレベルのMakefileは次のように表示されます。
obj-y := mod1/ mod2/
all:
$(MAKE) -C /lib/modules/`uname -r`/build M=$(PWD) modules
clean:
$(MAKE) -C /lib/modules/`uname -r`/build M=$(PWD) clean
$(RM) Module.markers modules.order
mod1/にあるMakefileとmodule1.cは、次のように表示されます。
SRCS = module1.c
OBJS = $(SRCS:.c=.o)
obj-m += $(OBJS)
EXTRA_CFLAGS += -I${PWD}/include
all:
$(MAKE) -C /lib/modules/`uname -r`/build M=$(PWD) modules
clean:
$(MAKE) -C /lib/modules/`uname -r`/build M=$(PWD) clean
$(RM) Module.markers modules.order
#include <linux/module.h>
#include <linux/kernel.h>
static int __init hello_start(void)
{
printk(KERN_INFO "Loading m1 module ...\n");
m2_func();
return 0;
}
static void __exit hello_end(void)
{
printk(KERN_INFO "Unloading m1 ...\n");
}
module_init(hello_start);
module_exit(hello_end);
MODULE_LICENSE("GPL");
mod2/にあるMakefileとmodule2.cは、次のように表示されます。
SRCS = module2.c
OBJS = $(SRCS:.c=.o)
obj-m += $(OBJS)
EXTRA_CFLAGS += -I${PWD}/include
all:
$(MAKE) -C /lib/modules/`uname -r`/build M=$(PWD) modules
clean:
$(MAKE) -C /lib/modules/`uname -r`/build M=$(PWD) clean
$(RM) Module.markers modules.order
#include "m2_func.h"
#include <linux/module.h>
#include <linux/kernel.h>
static int __init hello_start(void)
{
printk(KERN_INFO "Loading m2 module ...\n");
return 0;
}
static void __exit hello_end(void)
{
printk(KERN_INFO "Unloading m2 ...\n");
}
void m2_func(void)
{
printk(KERN_INFO "This a function in m2\n");
}
module_init(hello_start);
module_exit(hello_end);
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(m2_func);
NOTE cファイルごとに*.koを生成してしまうので、あなたのmakefileは使えません。Makefile はちゃんと仕事をしていますよ。ko' ファイルはカーネルオブジェクトファイルで、.c ソースファイルごとに 1 つ生成されます。これを回避する方法はありません。もし、複数の ko ファイルを必要としないのであれば、すべてのコードを 1つのソースファイルにまとめてください。
関連
-
[解決済み】GCC Cコードで静的宣言が非静的宣言に続くことを解決するには?
-
[解決済み】 error: too few arguments to function `printDay' (C言語)
-
[解決済み】「無効なイニシャライザー」と表示されるのですが、何が間違っているのでしょうか?
-
[解決済み】MB/sとMiB/sを計算する方法は?
-
[解決済み】fgetsによるセグメンテーションフォールト(コアダンプ) - と思う。
-
[解決済み】sizeof float (3.0) vs (3.0f)
-
[解決済み】エラー:呼び出されたオブジェクトは、関数または関数ポインタではない
-
[解決済み】makefile:4。*** missing separator. 停止する
-
[解決済み】.axfファイルとは何ですか?
-
[解決済み] insmod エラー: './hello.ko' を挿入: -1 無効なモジュール形式".
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】MB/sとMiB/sを計算する方法は?
-
[解決済み】サイズ8の無効な読み取り - Valgrind + C
-
[解決済み】LinuxのI_PUSHに相当するもの
-
[解決済み】インクリメントオペランドとして lvalue が必要です。
-
[解決済み】なぜか。"エラー: 配列型を持つ式への代入"
-
[解決済み】Makefile:1: ***セパレータがありません。停止します。
-
[解決済み】makefile:4。*** missing separator. 停止する
-
[解決済み】警告:式の結果が未使用の場合
-
[解決済み】execvp: バッドアドレスエラー
-
[解決済み】c - 警告:関数 'printf'の暗黙の宣言