Linuxのカーネルモジュールを作って遊んでみる
今回はLinuxのカーネルモジュール(例えばデバイスドライバ)のプログラミングにトライします。
まず今回はHello World的プログラムを作り、次回は/procファイルシステムへのアクセスなど色々試して遊んでみたいと思います。
環境はLinux(CentOS 7)(64bit)です。
目次
カーネルモジュールとは
カーネル・モジュールはLinuxのユーザー空間ではなくカーネル空間で動作するプログラムの事です。
例としてデバイスドライバと呼ばれるものはカーネルモジュールの1つのです。
ユーザー空間のアプリケーションのプログラミングとは少々お作法が事なります。
【参考】
まずはHello World
どんなプログラミングでも最初はやはりHello Worldを試すのが一般的ですので今回も例にもれずやっていきます。
事前にカーネルモジュールのプログラミングに必要なものをインストールします。
# カーネルモジュール開発に必要なパッケージをインストール
[user@localhost ~]$ sudo yum install kernel-devel
[user@localhost ~]$ sudo yum install kernel-headers
# インストール後の確認
# devel, heeadersがインストールされていればOKです。
[user@localhost ~]$ rpm -aq|grep kernel
kernel-tools-libs-3.10.0-514.26.2.el7.x86_64
kernel-tools-3.10.0-514.26.2.el7.x86_64
kernel-3.10.0-327.el7.x86_64
kernel-3.10.0-514.26.2.el7.x86_64
kernel-headers-3.10.0-693.5.2.el7.x86_64
kernel-devel-3.10.0-514.26.2.el7.x86_64
kernel-devel-3.10.0-693.5.2.el7.x86_64
準備が整ったらdmesgにHello Worldのログを出力するmymod.cとビルドするためのMakefileを作ります。
mymod.c
#include <linux/module.h>
#include <linux/init.h>
/* お約束的な宣言 */
MODULE_LICENSE("GPL");
/* insmod実行時に呼び出される */
static int mymod_init(void)
{
printk(KERN_INFO "Hello World\n");
return 0;
}
/* rmmod実行時に呼び出される */
static void mymod_exit(void)
{
printk(KERN_INFO "Goodbye World\n");
}
/* 関数の登録 */
module_init(mymod_init);
module_exit(mymod_exit);
Makefile
obj-m := mymod.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
makeを実行するとビルドが開始されます。ビルド後の出来上がった*.koのファイルがカーネルモジュールです。
[user@localhost driver]$ ls
Makefile mymod.c
[user@localhost driver]$ make
make -C /lib/modules/3.10.0-514.26.2.el7.x86_64/build M=/home/user/driver modules
make[1]: Entering directory `/usr/src/kernels/3.10.0-514.26.2.el7.x86_64'
CC [M] /home/user/driver/mymod.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/user/driver/mymod.mod.o
LD [M] /home/user/driver/mymod.ko
make[1]: Leaving directory `/usr/src/kernels/3.10.0-514.26.2.el7.x86_64'
[user@localhost driver]$ ls -lrt
total 204
-rw-rw-r--. 1 user user 156 Nov 2 23:00 Makefile
-rw-rw-r--. 1 user user 787 Nov 2 23:01 mymod.mod.c
-rw-rw-r--. 1 user user 0 Nov 2 23:01 Module.symvers
-rw-rw-r--. 1 user user 52864 Nov 2 23:01 mymod.mod.o
-rw-rw-r--. 1 user user 422 Nov 2 23:03 mymod.c
-rw-rw-r--. 1 user user 44400 Nov 2 23:04 mymod.o
-rw-rw-r--. 1 user user 34 Nov 2 23:04 modules.order
-rw-rw-r--. 1 user user 94184 Nov 2 23:04 mymod.ko ★これがカーネルモジュール
実行結果
カーネルモジュールが出来上がったので実際にロードしてみます。
insmodコマンドでカーネルにモジュールをロード、lsmodでロード中のモジュールを確認できます。
[user@localhost driver]$ sudo insmod mymod.ko
[user@localhost driver]$ lsmod |grep mymod
mymod 12496 0
[user@localhost driver]$ dmesg |tail
[ 1121.612492] mymod: loading out-of-tree module taints kernel.
[ 1121.612524] mymod: module verification failed: signature and/or required key missing - tainting kernel
[ 1121.612713] Hello World
カーネルモジュールのロードとdmesgにHello Worldが出力されていることが確認できました。
今度はrmmodでモジュールをアンロードしてみます。
[user@localhost driver]$ sudo rmmod mymod
[user@localhost driver]$ lsmod |grep mymod
[user@localhost driver]$
[user@localhost driver]$ dmesg |tail
[ 1121.612492] mymod: loading out-of-tree module taints kernel.
[ 1121.612524] mymod: module verification failed: signature and/or required key missing - tainting kernel
[ 1121.612713] Hello World
[ 1179.087241] Goodbye World
こちらも期待通りdmesgにメッセージが出力されていますね。
次回はもう少し実用的なプログラムを作ってみます。
コメント