このチュートリアル に従って、最初のドライバーを作成します。
Makefileは次のとおりです。
# Makefile – makefile of our first driver
# if KERNELRELEASE is defined, we've been invoked from the
# kernel build system and can use its language.
ifneq (${KERNELRELEASE},)
obj-m := ofd.o
# Otherwise we were called directly from the command line.
# Invoke the kernel build system.
else
KERNEL_SOURCE := /usr/src/linux 3.8
PWD := $(Shell pwd)
default:
${MAKE} -C ${KERNEL_SOURCE} SUBDIRS=${PWD} modules
clean:
${MAKE} -C ${KERNEL_SOURCE} SUBDIRS=${PWD} clean
endif
そして、ドライバーコードは:
* ofd.c – Our First Driver code */
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>
static int __init ofd_init(void) /* Constructor */
{
printk(KERN_INFO "Namaskar: ofd registered");
return 0;
}
static void __exit ofd_exit(void) /* Destructor */
{
printk(KERN_INFO "Alvida: ofd unregistered");
}
module_init(ofd_init);
module_exit(ofd_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Anil Kumar Pugalia <email_at_sarika-pugs_dot_com>");
MODULE_DESCRIPTION("Our First Driver");
作成中にエラーは発生しません。しかし、insmod ofd.ko
読み込めません。 dmesg
には次のように書かれています:
シンボルmodule_layoutのバージョンについて同意しない
uname -r
は「3.8.0-38-generic」を返し、カーネルソースも3.8です。modprobe -f ofd.ko
も失敗するまた:
#56~precise1-Ubuntu SMP Thu Mar 13 16:23:47 UTC 2014
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 12.04.4 LTS
Release: 12.04
Codename: precise
何が起こっている?
Linuxカーネルにはデータ構造が含まれており、そのレイアウトはバージョンごとにだけでなく、コンパイルオプションによっても異なります。その結果、カーネルモジュールをコンパイルするときは、カーネルソースからのヘッダーファイルだけでなく、カーネルのコンパイル中に生成されるいくつかのヘッダーファイルも必要です。カーネルソースを解凍するだけでは不十分です。
CONFIG_MODVERSIONS
を使用して構築されたカーネルでは、バージョン番号が異なる場合がありますが、データ構造のレイアウトは同じである必要があります。このオプションは、Ubuntuカーネルでアクティブ化されます。このオプションを使用する場合、ヘッダーに加えて、モジュールを適切なModule.symvers
ファイルに対してコンパイルする必要があります。 Ubuntuは、ほとんどのディストリビューションと同様に、このファイルを、コンパイル結果のカーネルヘッダーと同じパッケージに含めます。 Ubuntuカーネルヘッダーパッケージはlinux-headers-VERSION-VARIANT
と呼ばれます。 linux-headers-3.8.0-38-generic
。
CONFIG_MODVERSIONS
なしでビルドされたカーネル(独自のカーネルをコンパイルした場合など)では、モジュールのロード時のチェックは単純なバージョンチェックです。解凍されたカーネルソースを取得し、実行中のカーネルのコンパイル中に使用された.config
をコピーして、make modules_prepare
を実行できます。カーネルに加えたパッチがバイナリ互換性に影響を与えないことを確認する責任はあなたにあります。