それが僕には楽しかったんです。

いろんなレイヤーに居ます

最速のEchoサーバーを目指して、LinuxKernelモジュールを作っていく part1

はじめに

これから諸事情でLinux Kernel moduleとして動作する最速(?)のEchoサーバを作ることになったので
Echoサーバを作る過程をまとめていく。
今回はとりあえず、環境構築からKernel moduleで「Hello,World」的なことをするまでをやる

開発環境構築

参考にしたのは次の2つ
前者では主に、開発環境の面を、後者でコード周りを参考にした。

カーネルモジュール作成によるlinuxカーネル開発入門 - 第一回 hello world - Qiita
Linux kernel module の作成 - Qiita


VM的なのを使いたいなら特に前者を、そうでなくてよくてバグを踏んだ瞬間OSが死んでいいなら後者で十分だと思う。
これがメインではないので関連記事を参照して欲しい。

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

とりあえずCで開発するのでMakefileを作る
今までこういったものまともに書いたことないので今のところはふたつ目の参考記事のものをパクる。


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

obj-m := fastecho.o
fastecho-objs := fastecho_module.o


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

clean:
	rm -f *.o *.ko *.mod.c *.symvers *.order .fastecho*
	rm -fr .tmp_versions

次に、カーネルモジュール本体のコードを書く

#include<linux/module.h>
#include<linux/kernel.h>

MODULE_DESCRIPTION("The fastest echo server in kernel module");
MODULE_AUTHOR("lrf141");
MODULE_LICENSE("MIT");


static int fastecho_init_module(void){
  
  printk("Fastest Echo Server!!");

  return 0;
}


static void fastecho_cleanup_module(void){

  printk("Fastest Echo Server is unloaded!");

}

module_init(fastecho_init_module);
module_exit(fastecho_cleanup_module);

カーネルモジュールを書く上で、一行目のlinux/module.hは必ず必要となる。
include文の次に来る、大文字のあれこれはそれぞれモジュールの情報で
上から、そのモジュールの説明文、作者、ライセンスとなっている。

そのあとにはモジュールとして呼び出す関数が2つあるが、その両方で使用しているprintkはstdio.hを使った時のprintfのような機能がある。

末尾二行にあるmodule_init()関数ではカーネルモジュールがロードされた際に引数で渡した関数を呼び出す。
引数として渡す関数はintを返り値としている。

module_exit()関数では、カーネルモジュールがアンロードされた時に引数の関数を実行する。

ソースコードがかけたらとりあえずmakeする。


そのあとこれらモジュールの情報は次のようにすると見れる。

$ modinfo fastecho.ko
filename:       /home/lrf141/cProject/fastest_echo/fastecho.ko
license:        MIT
author:         lrf141
description:    The fastest echo server in kernel module
srcversion:     B5F9EFB5EC209D9B991796D
depends:        
vermagic:       4.4.0-98-generic SMP mod_unload modversions 

モジュールをロードするときは次のようにする

$ sudo insmod fastecho.ko

モジュールをアンロードするときはこれ。

$ sudo rmmod fastecho.ko

ただこれではprintkで出力された文字列が見れない。
ということでここまで終わった段階でdmesgコマンドでカーネルのバッファ出力内容をみる
ただ見るだけでは見づらいのでgrepも組み合わせる。

$ dmesg | grep "Fast"
[46074.578777] Fastest Echo Server!!
[46079.485027] Fastest Echo Server is unloaded!

するとprintkした内容が見えている。

最後に

今回は簡単なモジュールの制作をやったので次回はこれにネットワークの機能を突っ込みたい