今回はLinuxのカーネルモジュール(例えばデバイスドライバ)のプログラミングにトライします。
まず今回はHello World的プログラムを作り、次回は/procファイルシステムへのアクセスなど色々試して遊んでみたいと思います。
環境はLinux(CentOS 7)(64bit)です。
カーネルモジュールとは
カーネル・モジュールはLinuxのユーザー空間ではなくカーネル空間で動作するプログラムの事です。
例としてデバイスドライバと呼ばれるものはカーネルモジュールの1つのです。
ユーザー空間のアプリケーションのプログラミングとは少々お作法が事なります。
【参考】
まずはHello World
どんなプログラミングでも最初はやはりHello Worldを試すのが一般的ですので今回も例にもれずやっていきます。
事前にカーネルモジュールのプログラミングに必要なものをインストールします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# カーネルモジュール開発に必要なパッケージをインストール [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 |
1 |
準備が整ったらdmesgにHello Worldのログを出力するmymod.cとビルドするためのMakefileを作ります。
mymod.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#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); |
1 |
Makefile
1 2 3 4 5 6 7 |
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 |
1 |
makeを実行するとビルドが開始されます。ビルド後の出来上がった*.koのファイルがカーネルモジュールです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
[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 ★これがカーネルモジュール |
1 |
実行結果
カーネルモジュールが出来上がったので実際にロードしてみます。
insmodコマンドでカーネルにモジュールをロード、lsmodでロード中のモジュールを確認できます。
1 2 3 4 5 6 7 8 9 10 11 12 |
[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 |
1 |
カーネルモジュールのロードとdmesgにHello Worldが出力されていることが確認できました。
今度はrmmodでモジュールをアンロードしてみます。
1 2 3 4 5 6 7 8 9 10 11 12 |
[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 |
1 |
こちらも期待通りdmesgにメッセージが出力されていますね。
次回はもう少し実用的なプログラムを作ってみます。