Howto

カーネルモジュールの作成

本 Howto では、ターゲットボードで動作する Linux カーネルモジュールを作成する方法と、作成したカーネルモジュールをターゲットボードで動作させる方法を説明します。

カーネルモジュールとは、必要なときに動的にカーネルにロードまたはアンロードし、カーネルの機能を拡張することができるプログラムです。通常、デバイスドライバなどに使用されます。

本 Howto では、ロード時とアンロード時にメッセージを表示するだけの、簡単なカーネルモジュールを作成します。ビルドは、atmark-distに手を加えない、Out of Treeでおこないます。なお、使用する Linux カーネルは、2.6系を想定しています。

おおまかな手順は下記のようになります。

  1. atmark-distを使用して、カーネルをビルドする。
  2. カーネルモジュールをビルドする。
  3. カーネルイメージにモジュールを組み込む
  4. カーネルにモジュールをロード/アンロードする。

1. atmark-distを使用して、カーネルをビルドする。

カーネルモジュールを作成する前の準備として、atmark-dist Developpers Guideなどを参考に、ターゲットボード用のカーネルをビルドしてください。ターゲットボードで動作しているカーネルのバージョンと、ビルドに使用するカーネルのバージョンは一致している必要があります。

2. カーネルモジュールをビルドする。

今回はOut of Treeコンパイルで作成するので、まず、atmark-distの外にソースファイルとMakefileを用意します。作成するカーネルモジュールのモジュール名は、hello とします。

[PC ~]$ ls
atmark-dist
[PC ~]$ mkdir hello_module
[PC ~]$ ls
atmark-dist hello_module
[PC ~]$ ls hello_module
Makefile hello.c

hello.cは下記のものを使用します。

/*
 * Kernel Module Sample
 * file name: hello.c
 */
#include <linux/module.h>
#include <linux/init.h>

MODULE_LICENSE("GPL v2");

/* インストール時に実行 */
static int hello_init(void) {
    printk(KERN_ALERT "Hello World!\n");
    return 0;
}

/* アンインストール時に実行 */
static void hello_exit(void) {
    printk(KERN_ALERT "Goodbye World!\n");
}

module_init(hello_init);
module_exit(hello_exit);

Makefileは下記のものを使用します。

MODULES = hello.o

ifneq ($(KERNELRELEASE), )

obj-m := $(MODULES)
#CFLAGS_MODULE += -DDEBUG

else

ROOTDIR ?= ../atmark-dist

ROMFSDIR = $(ROOTDIR)/romfs

include $(ROOTDIR)/.config
include $(ROOTDIR)/config.arch

MAKEARCH = $(MAKE) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE)

LINUXDIR = $(CONFIG_LINUXDIR)
KERNELRELEASE = ${shell make -sC $(ROOTDIR)/$(LINUXDIR) kernelrelease}

all: modules romfs

modules:
        $(MAKEARCH) -C $(ROOTDIR)/$(LINUXDIR) M=${shell pwd} modules

romfs:
        make -C $(ROOTDIR) INSTALL_MOD_DIR=kernel \
        M=${shell pwd} modules_install
        $(ROOTDIR)/user/busybox/examples/depmod.pl -b \
        $(ROMFSDIR)/lib/modules/$(KERNELRELEASE) &> /dev/null

clean:
        -rm -f *.[oas] *.ko *.mod.c .*.d .*.tmp .*.cmd *.symvers
        -rm -rf .tmp_versions

distclean: clean
        -rm -f *~

endif

MODULES には <モジュール名>.o[1] を、ROOTDIR には atmark-dist のディレクトリを指定してください。

準備ができたら、カーネルモジュールをビルドします。ビルドには make コマンドで moduels ターゲットを使用します。ビルドが完了するとモジュールファイル hello.ko がディレクトリ内に生成されます。

[PC ~]$ cd hello_module
[PC ~/hello_module]$ make modules
[PC ~/hello_module]$ ls
Makefile  hello.c  hello.ko  hello.mod.c  hello.mod.o  hello.o

3. カーネルイメージにモジュールを組み込む

手順2. で作成した、モジュールファイル hello.ko を、そのままターゲットボードへコピーしても動作させることもできますが、今回はカーネルイメージにモジュールを組み込む方法を紹介します。

モジュールファイルを atmark-dist の romfs ディレクトリにインストールするために、make コマンドで romfs ター ゲットを指定します。[2][3]

[PC ~/hello_module]$ make romfs
[PC ~/hello_module]$  ls ../atmark-dist/romfs/lib/modules/2.6.12.3-a9-13/kernel/
hello.ko

次に、atmark-dist のディレクトリに移動して、make image を実行することで、hello.ko モジュールを含んだターゲットボード用のイメージファイルがimage ディレクトリに生成されます。

[PC ~/hello_module]$ cd ../atmark-dist/
[PC ~/atmark-dist]$ make image
[PC ~/atmark-dist]$ ls images/
linux.bin  linux.bin.gz  romfs.img  romfs.img.gz

4. カーネルにモジュールをロード/アンロードする。

ターゲットボードに、作成したカーネル及びユーザーランドのイメージを書き込みます。

カーネルモジュールのロードは、insmodでおこないます。[3]

[armadillo ~]# insmod /lib/modules/2.6.12.3-a9-13/kernel/hello.ko
Hello World!

現在カーネルにロードされているモジュールは、lsmod または /proc/modules によって調べることができます。

[armadillo ~]# lsmod
Module                  Size  Used by    Not tainted
hello 928 0 - Live 0xbf000000
[armadillo ~]# cat /proc/modules
hello 928 0 - Live 0xbf000000

アンロードはrmmodでおこなうことができます。

[armadillo ~]# rmmod hello
Goodbye World!
[armadillo ~]# lsmod
Module                  Size  Used by    Not tainted

本 Howto で使用したソースコードは、下記から取得することができます。

ダウンロード


[1] 最終的に作成されるカーネルモジュールは、<モジュール名>.ko という名前になりますが、MODULES に指定するのは <モジュール名>.o という名前です。

[2] 事前に、atmark-dist ディレクトリでmake をおこない、romfs ディレクトリを作成しておく必要があります。

[3] パス中の「2.6.12.3-a9-13」の部分は、カーネルのバージョンによって変わりますので、適宜読みかえてください。