mcommit's message

ソフトウェア開発の仕事をしているsimotinといいます。記事の内容でご質問やご意見がありましたらお気軽にコメントしてください\^o^/

Linuxのカーネルモジュールを書いてみた

今年の1月に書いた、2017年にやりたいこと

mcommit.hatenadiary.com

Linuxデバイスドライバを書いてみる

というのを挙げておりましたが、この12月に至っても達成できていなかったのでとりあえずLinux mint上でカーネルモジュールを書いてみました。
書いたといってもロードとアンロードしかできない、まさにカーネルモジュールのhello world程度のものです。

書いてみたコード

  • kmod.c
#include <linux/module.h>
#include <linux/init.h>

MODULE_LICENSE("Dual BSD/GPL");

static int hello_init(void)
{
	printk(KERN_ALERT "driver loaded, hello kernel.\n");
	return 0;
}

static void hello_exit(void)
{
	printk(KERN_ALERT "driver unloaded, good bye kernel.\n");
}

module_init(hello_init);
module_exit(hello_exit);
obj-m += kmod.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 を実行し、正常にビルドできると kmod.ko が生成されています。


$ file kmod.ko
kmod.ko: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), BuildID[sha1]=0acdb23dfc45137854b91cb3edbb2ed09f205e78, not stripped

modinfo でカーネルモジュールの情報が取得できます。
上記のkmod.cではLicenceくらいしか情報を埋め込んでいませんが、色々とモジュールに情報を埋め込むマクロがあるようです。


$ modinfo kmod.ko
filename: /home/miyazaki/driver/kmod.ko
license: Dual BSD/GPL
srcversion: F5A8F473E31B45AC339CFDB
depends:
vermagic: 4.4.0-21-generic SMP mod_unload modversions

ロードとアンロード

insmodでカーネルモジュールのロード

ロードされているモジュールの確認はlsmodコマンドを使います。


$ sudo insmod kmod.ko

$ lsmod | grep kmod
kmod 16384 0

16384はモジュールのサイズ。最後の0は参照カウンタの値になるそうです。

rmmodでカーネルモジュールのアンロードができます。


$ sudo rmmod kmod

printkの出力先

printkの出力先は標準出力でも標準エラー出力でもありません。
カーネルリングバッファになるそうです。確認は dmsegから。


$ dmesg
...(略)
[26564.817444] driver loaded, hello kernel.
[27166.340079] driver unloaded, good bye kernel.

おぉ。printkも文字列が出力されています。

感想

module_initとかmodule_exitとかrubyの拡張ライブラリとかと雰囲気にてとっつきやすかったです。
コード自体は単純なので、肝になるのは参照しているMakefileの中身だと思いみてみました。

今回私が試した環境は、


$uname -a
Linux mint 4.4.0-21-generic #37-Ubuntu SMP Mon Apr 18 18:33:37 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

になります。

make -C で参照しているMakefileは /lib/modules/4.4.0-21-generic/build/Makefile にありました。
1600行ぐらいあって、ざっと見ただけでは何が重要なのかわかりませんでした。まぁこの編は必要になったらおいおい勉強ということで・・・

initとexitだけではカーネルモジュールをあまり書いてみた意味がないので今回を取っ掛りとしてもう少し何かデバドラ的なことをしてみたいです。

でもカーネルモジュールで書くメリットとは何なんだろう・・・

  • ハードのデバドラ
  • アプリで書くより早い!?(パフォーマンス面)

とかなんだろうか。

参考にした書籍

Linuxデバイスドライバプログラミング

Linuxデバイスドライバプログラミング

RaspberryPiで学ぶ ARMデバイスドライバープログラミング

RaspberryPiで学ぶ ARMデバイスドライバープログラミング

最初はラズパイのデバドラを作るのを試していましたが、GPIOのレジスタの種類が多そうな感じだったのでとりあえずPC上で何もしないカーネルモジュールを書いてみることにしました。カーネルでGPIO触るだけでもLinuxだと色々と覚えることがありますね。ワンチップマイコンだと方向レジスタとデータレジスタ触るだけでいいのに。