linuxカーネルモジュールのプログラミング時に複数のソースファイルMakefileが書かれている問題について
3194 ワード
カーネルモジュールのプログラミングを勉強している間に、Makefileが正しく書かれていないことによる問題に遭遇しました.ひとつcソースファイルのMakefileはネット上の大部分の資料によって紹介されているように問題はありません.複数のソースファイルのカーネルモジュールをプログラミングするとき、問題が発生して、自分で半日悩んで、最後に資料を調べて、大神に教えてもらってやっと解決しました.過程と解決方法を貼って、みんなの参考にして、一緒に勉強します.
カーネルモジュールのプログラミングの例を説明する記事がたくさんあります.例えば、次の簡単な例です.
Makefileファイルは次のように記述されています.
これは一つです.cソースファイルの場合、やはり便利です.この書き方では、obj-m+=hello.ここのハローきっとハローcソースファイルのファイル名(たとえば、あなたのソースファイルがabc.cである場合、Makefileにはobj-m+=abc.oと書くべきです.そうしないと、makeの場合、次のエラーが表示されます.
ここのmod.oは私が勝手に命名したモジュール名で、現在のディレクトリの下にmodがないため、エラーが発生しました.c.
自分のモジュールに名前を付けてもいいですか?もちろん
同じようにcを例として,モジュール名を随意に命名したMakefileを記述し,単純な指定モジュールは依存するターゲットファイルを構築し,そのMakefileは以下のようになる.
ここで1行のコードABC-objs:=hello.o、ABCを確立することを指定する.o依存ターゲットファイルhello.o、これで私たちは勝手に自分のモジュールに名前をつけることができます.
2番目のMakefileの書き方をお勧めします.モジュール名を自由に命名できるだけでなく、複数のソースファイルで1つのカーネルモジュールをコンパイルする問題にも関連しています.
最初のMakefileの書き方はソースファイルを1つしかコンパイルできません.makeの場合、obj-m値と同じ名前のソースファイルにデフォルトで依存してコンパイルされるためです.しかし、モジュールが処理する問題が比較的複雑な場合は、ソースコードを複数のソースファイルに配置して構築したい場合があります.hファイルで管理します.たとえば、hello.c hello1.c hello1.h;
最初のMakefileの書き方に従えば、obj-m+=helloと書くかもしれません.o hello1.o.このように書かれたMakefileはmake段階では間違っていませんが、insmod./hello.koの場合は次のようなエラーが発生します.
insmod: ERROR: could not insert module./hello.ko: Unknown symbol in module
解決策は,第2のMakefileの書き方のように,モジュール依存ターゲットファイルをobjsで一つ一つ列挙し,完全な複数のソースファイルのMakefileファイルを以下のように記述することである.
カーネルモジュールのプログラミングの例を説明する記事がたくさんあります.例えば、次の簡単な例です.
#hello.c
#ifndef __KERNEL__
#define __KERNEL__
#endif //__KERNEL__
#ifndef MODULE
#define MODULE
#endif //MODULE
#include
#include
#include
static __init int hello_init(void)
{
printk(KERN_INFO"hello linux kernel module ...\r
");
return 0;
}
static __exit void hello_exit(void)
{
printk(KERN_INFO"goodbye linux kernel module ...\r
");
return 0;
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
Makefileファイルは次のように記述されています.
ifneq ($(KERNELRELEASE),)
obj-m += hello.o
else
CURRENT_PATH:=$(shell pwd)
VERSION_NUM:=$(shell uname -r)
LINUX_PATH:=/usr/src/linux-headers-$(VERSION_NUM)
all:
make -C $(LINUX_PATH) M=$(CURRENT_PATH) modules
clean:
make -C $(LINUX_PATH) M=$(CURRENT_PATH) clean
endif
これは一つです.cソースファイルの場合、やはり便利です.この書き方では、obj-m+=hello.ここのハローきっとハローcソースファイルのファイル名(たとえば、あなたのソースファイルがabc.cである場合、Makefileにはobj-m+=abc.oと書くべきです.そうしないと、makeの場合、次のエラーが表示されます.
*** No rule to make target`/home/share/filter/test/mod.c', needed by`/home/share/filter/test/mod.o'. Stop.
ここのmod.oは私が勝手に命名したモジュール名で、現在のディレクトリの下にmodがないため、エラーが発生しました.c.
自分のモジュールに名前を付けてもいいですか?もちろん
同じようにcを例として,モジュール名を随意に命名したMakefileを記述し,単純な指定モジュールは依存するターゲットファイルを構築し,そのMakefileは以下のようになる.
ifneq ($(KERNELRELEASE),)
obj-m += ABC.o
ABC -objs:=hello.o
else
CURRENT_PATH:=$(shell pwd)
VERSION_NUM:=$(shell uname -r)
LINUX_PATH:=/usr/src/linux-headers-$(VERSION_NUM)
all:
make -C $(LINUX_PATH) M=$(CURRENT_PATH) modules
clean:
make -C $(LINUX_PATH) M=$(CURRENT_PATH) clean
endif
ここで1行のコードABC-objs:=hello.o、ABCを確立することを指定する.o依存ターゲットファイルhello.o、これで私たちは勝手に自分のモジュールに名前をつけることができます.
2番目のMakefileの書き方をお勧めします.モジュール名を自由に命名できるだけでなく、複数のソースファイルで1つのカーネルモジュールをコンパイルする問題にも関連しています.
最初のMakefileの書き方はソースファイルを1つしかコンパイルできません.makeの場合、obj-m値と同じ名前のソースファイルにデフォルトで依存してコンパイルされるためです.しかし、モジュールが処理する問題が比較的複雑な場合は、ソースコードを複数のソースファイルに配置して構築したい場合があります.hファイルで管理します.たとえば、hello.c hello1.c hello1.h;
最初のMakefileの書き方に従えば、obj-m+=helloと書くかもしれません.o hello1.o.このように書かれたMakefileはmake段階では間違っていませんが、insmod./hello.koの場合は次のようなエラーが発生します.
insmod: ERROR: could not insert module./hello.ko: Unknown symbol in module
解決策は,第2のMakefileの書き方のように,モジュール依存ターゲットファイルをobjsで一つ一つ列挙し,完全な複数のソースファイルのMakefileファイルを以下のように記述することである.
ifneq ($(KERNELRELEASE),)
obj-m += ABC.o
ABC -objs:=hello.o hello1.h
else
CURRENT_PATH:=$(shell pwd)
VERSION_NUM:=$(shell uname -r)
LINUX_PATH:=/usr/src/linux-headers-$(VERSION_NUM)
all:
make -C $(LINUX_PATH) M=$(CURRENT_PATH) modules
clean:
make -C $(LINUX_PATH) M=$(CURRENT_PATH) clean
endif