本 Howto では、ターゲットボードで動作する Linux カーネルモジュールを作成する方法と、作成したカーネルモジュールをターゲットボードで動作させる方法を説明します。
カーネルモジュールとは、必要なときに動的にカーネルにロードまたはアンロードし、カーネルの機能を拡張することができるプログラムです。通常、デバイスドライバなどに使用されます。
本 Howto では、ロード時とアンロード時にメッセージを表示するだけの、簡単なカーネルモジュールを作成します。ビルドは、atmark-distに手を加えない、Out of Treeでおこないます。なお、使用する Linux カーネルは、2.6系を想定しています。
おおまかな手順は下記のようになります。
- atmark-distを使用して、カーネルをビルドする。
- カーネルモジュールをビルドする。
- カーネルイメージにモジュールを組み込む
- カーネルにモジュールをロード/アンロードする。
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」の部分は、カーネルのバージョンによって変わりますので、適宜読みかえてください。