Posted at

カーネルモジュールを作成してみる

More than 1 year has passed since last update.

helloを出力するだけの簡単なカーネルモジュールを作成してみる。


環境の作成

gccなど既に入っているのであればここは不要である。

クリーンな環境を想定するので以下のdockerコンテナで作業する。

$ docker run --rm -i -v /lib/modules:/lib/modules \

-v /usr/src/kernels/:/usr/src/kernels/ \
-v /tmp/hello:/tmp/hello \
-t centos:centos7 /bin/bash
# chmod 777 /tmp/hello
# cd /tmp/hello


  • 説明


    • 終了後削除されるコンテナを作成する(--rm)

    • ビルドに必要なデータをコンテナに渡す(-v)

    • コンテナではkmod(insmod,rmmod)が入らないのでホストへ受け渡し用にtmpを渡す

    • 権限を変えてしまうのは行儀が良くないが面倒なので気にしない




ビルドに必要なものをインストールする

ダウンロードとインストールに少々時間がかかるが、一行で済む。

# yum groupinstall "Development Tools" -y


  • 説明


    • 特になし。




ソースの作成

ここが本題。

hello.cとMakefileを作成する。

注意点としてはMakefileのインデントはTABなので下のをそのままコピペすると

Makefile:7: *** missing separator (did you mean TAB instead of 8 spaces?). Stop.

となる。

# useradd ymko

# su - ymko
$ cd /tmp/hello
$ ls
Makefile hello.c


hello.c

#include <linux/module.h>

#include <linux/kernel.h>

static int __init hello_init( void )
{
printk( KERN_INFO "hello module insmod\n" );
return 0;
}

static void __exit hello_exit( void )
{
printk( KERN_INFO "hello module rmmod\n" );
}

module_init( hello_init );
module_exit( hello_exit );

MODULE_DESCRIPTION( "hello world!" );
MODULE_LICENSE( "MIT" );



Makefile

obj-m := hello.o

KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
VERBOSE = 0

default:
$(MAKE) -C $(KDIR) M=$(PWD) KBUILD_VERBOSE=$(VERBOSE) modules

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



make

makeである。

$ make 

make -C /lib/modules/3.10.0-327.28.2.el7.x86_64/build M=/tmp/hello KBUILD_VERBOSE=0 modules
make[1]: Entering directory `/usr/src/kernels/3.10.0-327.28.2.el7.x86_64'
CC [M] /tmp/hello/hello.o
Building modules, stage 2.
MODPOST 1 modules
CC /tmp/hello/hello.mod.o
LD [M] /tmp/hello/hello.ko
make[1]: Leaving directory `/usr/src/kernels/3.10.0-327.28.2.el7.x86_64'


モジュールのロード・アンロード

ホスト側のroot権限で実行する。

なおコンテナではkmodがないのでinsmod,rmmodがない。kmodをインストールしようとうするとsystemdと衝突して入らない。

# cd /tmp/hello

# insmod hello.ko
# rmmod hello.ko
# dmesg | tail
[292475.726061] hello module insmod
[292488.733643] hello module rmmod


トラブルシュート



  • Makefile:7: *** missing separator (did you mean TAB instead of 8 spaces?). Stop.


    • Makefileのインデントがタブじゃない。




  • make: *** /lib/modules/3.10.0-327.28.2.el7.x86_64/build: No such file or directory. Stop.


    • /lib/modules/3.10.0-327.28.2.el7.x86_64/buildがない。

    • リンクが切れている場合はkernel-develがない。

    • ".config"がない。/boot/config-*をコピーしてmake oldconfig、make prepareをしないといけない




参考

Building External Modules(公式ドキュメント)

https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/tree/Documentation/kbuild/modules.txt

Building a custom kernel - FedoraProject

https://fedoraproject.org/wiki/Building_a_custom_kernel?rd=Docs/CustomKernel

HowTos/BuildingKernelModules - CentOS Wiki

https://wiki.centos.org/HowTos/BuildingKernelModules

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

http://www.hakodate-ct.ac.jp/~tokai/tokai/research/kmod.html

[Linux][kernel module] 簡単なローダブルカーネルモジュールのビルドとロード

http://qiita.com/koara-local/items/39002cc1f611e26114f8

SUBDIRS variable in kernel module makefile - Stack Overflow

http://stackoverflow.com/questions/21129224/subdirs-variable-in-kernel-module-makefile


Same as M=. The SUBDIRS= syntax is kept for backwards compatibility.

M =と同じです。SUBDIRS =構文は下位互換性のために保持されています。