無料Wikiサービス | デモページ
Linuxなどのメモ書き

Loadable Kernel Moduleの作り方


LinuxのLoadable Kernel Moduleの作り方のHowTo。対象のカーネルバージョンは2.6。

1. SourceとMakefile

カーネルにLoad/Unloadできるだけの小モジュールを作ってみる。何処か適当なディレクトリに以下のようにソースとMakefileを作る。ソースとMakefileの中身は以下を参照。.tar.gzにまとめたファイルはこちらから。

xxxxxx/
     Makefile   - Makefile
     small.c    - モジュールのソース

1.1 Source

モジュールのソースコードのサンプルを以下に示す。

最低限必要なのは、モジュールがLoadされた時に呼び出される初期化ルーチン(smallmod_init_module())とモジュールがUnloadされる時に呼び出される後処理用ルーチン(smallmod_init_module())。これらのルーチンは、それぞれmodule_init(),module_exit()マクロで指定する。

初期化ルーチンの返り値はint型で、正常に処理が終了した場合は0を返す。

インクルードファイルはmodule_init,exit()用にmodule.hが必要。あと、カーネルのconfigが必要な場合はconfig.hをインクルードする。以下ではprintk()でメッセージを出力しているのでkernel.hもインクルードしている。

MODULE_DESCRIPTION,MODULE_AUTHOR,MODULE_LICENSEもちゃんと書いておくとよい。これらの情報はモジュール(*.ko)の.modinfoセクションに書き込まれる。


small.c
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>

MODULE_DESCRIPTION("Small Test Module");
MODULE_AUTHOR("kztomita");
MODULE_LICENSE("GPL");

/* Moduleがロードされた時に呼び出される初期化ルーチン */
static int smallmod_init_module(void)
{
        int error = 0;

        /*
         * 初期化処理を行なう
         */
        printk("smallmod is loaded.\n");

        /* エラーの場合 */
        if (error)
                return  -ENODEV;

        return 0;
}

/* Moduleがアンロードされたる時に呼び出される後処理 */
static void smallmod_cleanup_module(void)
{
        printk("smallmod is unloaded.\n");
}

module_init(smallmod_init_module);
module_exit(smallmod_cleanup_module);


1.2 Makefile

Makefileのサンプルを以下に示す。このMakefileはsmall.cをコンパイルしてモジュールsmallmod.koを作成する。コンパイルは本Makefile単体では行なえず、カーネルソースツリーにあるMakefileを呼び出してカーネルモジュールコンパイルのルールを利用する。

obj-mには作成したいモジュールのファイル名を書く。拡張子は*.koではなく*.oなので注意。ここで指定したファイルが最終的にモジュール(*.ko)に変換される。

次にモジュールを構成するオブジェクトを指定する。指定するTarget名は<モジュール名>-obj。今回はobj-mにsmallmod.oを指定しているのでモジュール名はsmallmod。よって、smallmod-objにコンパイルするオブジェクト名を並べる。今回はソースがsmall.cだけなのでオブジェクトはsmall.oだけとなる。複数のソースをコンパイルする場合は、ここにオブジェクトを並べればよい。

今回のようにファイルが1つだけなら<モジュール名>-objのTargetは指定しなくてもよい。指定しなかった場合は、デフォルトのSuffix Ruleに従いsmallmod.cをコンパイルしに行く。今回例を示すためソースファイルをsmall.cに名前を変えている。

実際にコンパイルを行なう時はカーネルソースツリーのMakefileを使用する。引数に以下のものを指定する。

  • -C Option: カーネルソースツリーのパスを指定する。実際にLoadingさせたいカーネルと同じバージョンのツリーである必要があるので注意。(*1)
  • SUBDIRS:モジュールのソースがあるディレクトリを指定する。
  • KBUILD_VERBOSE:コンパイル時のメッセージ出力を制御する。コンパイル時の実行コマンドをそのまま表示したい場合は1にすればよい。
  • コンパイルTarget:modulesを指定する。
(*1) コンパイル時に使用したソースツリーのカーネルバージョンや一部のConfig(SMP,Preempt等)の情報がモジュールのvermagicに埋めこまれて、Loading時にチェックされるため。これがカーネルはvermagicが不一致だとLoadingを受けつけない。vermagicにはConfig情報も入るので、厳密にはバージョンだけでなくSMP,Preemptなど一部のConfigも合わせておかないといけない。

Makefile
KERNELSRCDIR = /usr/src/linux
BUILD_DIR := $(shell pwd)
VERBOSE = 0

# モジュール名
obj-m := smallmod.o

# <モジュール名>-objs にモジュールを構成するオブジェクトの一覧を列挙する
smallmod-objs := small.o

all:
        make -C $(KERNELSRCDIR) SUBDIRS=$(BUILD_DIR) KBUILD_VERBOSE=$(VERBOSE) modules

clean:
        rm -f *.o
        rm -f *.ko
        rm -f *.mod.c
        rm -f *~

2. コンパイル

ファイルのあるディレクトリでmakeを実行すればコンパイルできる。

モジュールのファイルはsmallmod.koファイル(Kernel 2.6のモジュールは拡張子がkoになる)。一緒に作成されているsmallmod.mod.cは、モジュールにカーネルバージョンなどを埋めこむ為のファイル。カーネルソースツリーのmake処理で勝手に生成される。

SourceでMODULE_DESCRIPTION()などで書き込んだ情報は以下のようにして確認できる。

#objdump smallmod.ko --full-contents --section=.modinfo

smallmod.ko:     ファイル形式 elf32-i386

セクション .modinfo の内容:
 0000 64657363 72697074 696f6e3d 536d616c  description=Smal
 0010 6c205465 7374204d 6f64756c 65006175  l Test Module.au
 0020 74686f72 3d6b7a74 6f6d6974 61006c69  thor=kztomita.li
 0030 63656e73 653d4750 4c000000 00000000  cense=GPL.......
 0040 7665726d 61676963 3d322e36 2e31342e  vermagic=2.6.14.
 0050 3320534d 50205045 4e544955 4d342067  3 SMP PENTIUM4 g
 0060 63632d33 2e340064 6570656e 64733d00  cc-3.4.depends=.

3. Load/Unload

3.1 Load

モジュールをLoadする。(root権限で行なうこと)

/sbin/insmod smallmod.ko
lsmodでモジュールがLoadされていることを確認できる。
# /sbin/lsmod
Module                  Size  Used by
smallmod                2176  0
ppp_deflate             5760  0
zlib_deflate           22552  1 ppp_deflate
    <略>
dmesgでモジュールの初期化ルーチンのprintk()のメッセージが出力されているのが確認できる。
# dmesg
  <略>
PPP generic driver version 2.4.2
PPP Deflate Compression module registered
smallmod is loaded.

3.2 Unload

モジュールのUnload。
/sbin/rmmod smallmod
モジュールが消えているのが確認できる。
# /sbin/lsmod
Module                  Size  Used by
ppp_deflate             5760  0
zlib_deflate           22552  1 ppp_deflate
dmesgで後処理ルーチンのメッセージが出力されているのが確認できる。
#dmesg
   <略>
PPP generic driver version 2.4.2
PPP Deflate Compression module registered
smallmod is loaded.
smallmod is unloaded.



最終更新 2007/02/17 12:55:57 - kztomita
(2006/09/02 16:08:52 作成)