カーネルモジュールとは?
カーネル モジュールは、必要に応じてカーネルからロードおよびアンロードできるコードの一部です。
カーネル モジュールは、カーネルを再構築または再コンパイルすることなく、ベース カーネルの機能を拡張する簡単な方法を提供します。ほとんどのドライバは、Linux カーネル モジュールとして実装されています。これらのドライバーが不要な場合は、その特定のドライバーのみをアンロードできます。これにより、カーネル イメージのサイズが縮小されます。
カーネル モジュールには .ko 拡張子が付きます。通常の Linux システムでは、カーネル モジュールは /lib/modules/
以前に、ソースからカーネルをコンパイルする方法について説明しました。
このチュートリアルでは、単純な Hello World の例を使用してカーネル モジュールを作成する方法について説明します。
I.カーネル モジュールを操作するユーティリティ
1. lsmod – すでにロードされているモジュールのリスト
lsmod コマンドは、以下に示すように、カーネルに既にロードされているモジュールを一覧表示します。
# lsmod Module Size Used by ppp_deflate 12806 0 zlib_deflate 26445 1 ppp_deflate bsd_comp 12785 0 ..
2. insmod – モジュールをカーネルに挿入
insmod コマンドは、以下に示すように新しいモジュールをカーネルに挿入します。
# insmod /lib/modules/3.5.0-19-generic/kernel/fs/squashfs/squashfs.ko # lsmod | grep "squash" squashfs 35834 0
3. modinfo – モジュール情報を表示
modinfo コマンドは、以下に示すように、カーネル モジュールに関する情報を表示します。
# modinfo /lib/modules/3.5.0-19-generic/kernel/fs/squashfs/squashfs.ko filename: /lib/modules/3.5.0-19-generic/kernel/fs/squashfs/squashfs.ko license: GPL author: Phillip Lougher description: squashfs 4.0, a compressed read-only filesystem srcversion: 89B46A0667BD5F2494C4C72 depends: intree: Y vermagic: 3.5.0-19-generic SMP mod_unload modversions 686
4. rmmod – カーネルからモジュールを削除
rmmod コマンドは、カーネルからモジュールを削除します。既にプログラムで使用されているモジュールを削除することはできません。
# rmmod squashfs.ko
5. modprobe – カーネルからモジュールを追加または削除
modprobe は、モジュール間の依存関係に基づいてモジュールをロード/アンロードするインテリジェントなコマンドです。詳細な例については、modprobe コマンドを参照してください。
II.シンプルな Hello World カーネル モジュールを作成する
1. Linux ヘッダーのインストール
以下に示すように、最初に linux-headers-.. をインストールする必要があります。ディストリビューションに応じて、apt-get または yum を使用してください。
# apt-get install build-essential linux-headers-$(uname -r)
2. Hello World モジュールのソース コード
次に、C プログラミング言語で次の hello.c モジュールを作成します。
#include <linux/module.h> // included for all kernel modules #include <linux/kernel.h> // included for KERN_INFO #include <linux/init.h> // included for __init and __exit macros MODULE_LICENSE("GPL"); MODULE_AUTHOR("Lakshmanan"); MODULE_DESCRIPTION("A Simple Hello World module"); static int __init hello_init(void) { printk(KERN_INFO "Hello world!\n"); return 0; // Non-zero return means that the module couldn't be loaded. } static void __exit hello_cleanup(void) { printk(KERN_INFO "Cleaning up module.\n"); } module_init(hello_init); module_exit(hello_cleanup);
警告: すべてのカーネル モジュールは、高度な特権モードであるカーネル空間で動作します。そのため、カーネル モジュールに記述する内容には注意してください。
3.カーネル モジュールをコンパイルする Makefile の作成
次の makefile を使用して、上記の基本的な hello world カーネル モジュールをコンパイルできます。
obj-m += hello.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 コマンドを使用して、hello world カーネル モジュールをコンパイルします。
# make make -C /lib/modules/3.5.0-19-generic/build M=/home/lakshmanan/a modules make[1]: Entering directory `/usr/src/linux-headers-3.5.0-19-generic' CC [M] /home/lakshmanan/a/hello.o Building modules, stage 2. MODPOST 1 modules CC /home/lakshmanan/a/hello.mod.o LD [M] /home/lakshmanan/a/hello.ko make[1]: Leaving directory `/usr/src/linux-headers-3.5.0-19-generic'
上記により、サンプル カーネル モジュールである hello.ko ファイルが作成されます。
4.サンプル カーネル モジュールの挿入または削除
hello.ko ファイルができたので、以下に示すように insmod コマンドを使用して、このモジュールをカーネルに挿入できます。
# insmod hello.ko # dmesg | tail -1 [ 8394.731865] Hello world! # rmmod hello.ko # dmesg | tail -1 [ 8707.989819] Cleaning up module.
モジュールがカーネルに挿入されると、module_init マクロが呼び出され、hello_init 関数が呼び出されます。同様に、モジュールが rmmod で削除されると、module_exit マクロが呼び出され、hello_exit が呼び出されます。 dmesg コマンドを使用して、サンプル カーネル モジュールからの出力を確認できます。
printk はカーネルで定義されている関数であり、IO ライブラリの printf と同様に動作することに注意してください。カーネル モジュールのライブラリ関数は使用できないことに注意してください。
これで、独自の Linux カーネル モジュールを作成するための基本を学びました。