このページの目次

Kbuild とモジュール

カバー範囲: Kconfig/Kbuild → Makefile 構文 → カーネルモジュールのコンパイル → 外部ツリーモジュール → モジュール署名 → EXPORT_SYMBOL → モジュールの読み込み カーネルバージョン: 2.6 ~ 6.x

Kbuild ビルドシステム

Kconfig: 設定項目

各サブディレクトリ: Kconfig ファイル → メニュー、オプション、依存関係を定義
  → make menuconfig/nconfig → Kconfig を読み込み → .config を生成

config エントリ:
  config MY_FEATURE
    tristate "My Feature"    ← y(組み込み), m(モジュール), n(コンパイルしない)
    depends on PCI
    select CRC32
    help
      この機能は...

  boolean: y/n
  tristate: y/m/n
  int/hex/string: 値

Kbuild Makefiles

# サブディレクトリの Makefile:
obj-y += core.o           # カーネルに組み込む (CONFIG_XXX=y)
obj-m += driver.o         # モジュールとしてコンパイル (CONFIG_XXX=m)
obj-$(CONFIG_MYDRV) += mydrv.o  # config に応じて y/m/n を決定

# 複数ファイルのモジュール:
obj-m := mymod.o
mymod-objs := mod-main.o mod-helper.o

コンパイルフロー

make defconfig          # デフォルト設定 (アーキテクチャ依存)
make menuconfig         # インタラクティブ設定
make -j$(nproc)         # パラレルコンパイル → vmlinux + modules
make modules_install    # モジュールを /lib/modules/<version>/ にインストール
make install            # カーネルと initramfs をインストール

カーネルモジュール

基本的な骨格

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

static int __init my_init(void) {
    pr_info("my_module: loaded\n");
    return 0;  // 0=成功, -ENODEV=デバイスなし, -ENOMEM=メモリ不足
}

static void __exit my_exit(void) {
    pr_info("my_module: unloaded\n");
}

module_init(my_init);
module_exit(my_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Example kernel module");
MODULE_AUTHOR("Name <email>");

モジュールの読み込み/アンロード

insmod mymodule.ko         # 読み込み + 依存関係のチェック
rmmod mymodule             # アンロード
modprobe mymodule          # 読み込み + 依存モジュールの自動読み込み
modprobe -r mymodule       # アンロード + 依存関係の再帰的アンロード

# 読み込まれているモジュールの確認
lsmod
cat /proc/modules

モジュールパラメータ

static int myparam = 42;
module_param(myparam, int, 0644);  // sysfs: /sys/module/mymod/parameters/myparam
// 使用方法: insmod mymodule.ko myparam=100

モジュール署名

// CONFIG_MODULE_SIG=y → コンパイル時にモジュールに署名
// カーネル起動時: 署名を検証 → 不一致 → 読み込み拒否 (sig_enforce=0 の場合を除く)
// UEFI Secure Boot: 署名検証を強制有効

// カーネルキーリング:
//   .builtin_trusted_keys: コンパイル時に埋め込まれた鍵
//   .secondary_trusted_keys: 実行時に追加 (builtin 署名が必要)

EXPORT_SYMBOL

// 記号 (関数/変数) を公開シンボルテーブルにエクスポート:
EXPORT_SYMBOL(my_function);        // すべてのモジュールで利用可能
EXPORT_SYMBOL_GPL(my_function2);   // GPL モジュールのみ利用可能 (ライセンスチェック)

// 仕組み: コンパイル時に __ksymtab セクションに記号を記録 → モジュール読み込み時に解決

外部ツリーモジュールのビルド

# 外部モジュール用の Kbuild (カーネルツリー外):
obj-m := mydriver.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

all:
    make -C $(KDIR) M=$(PWD) modules

clean:
    make -C $(KDIR) M=$(PWD) clean

参考

  • ソースコード⁠: scripts/kconfig/, scripts/Makefile.*, kernel/module/
  • カーネルドキュメント⁠: Documentation/kbuild/, Documentation/kbuild/modules.rst

キーワード: Kconfig, Kbuild, kernel module, EXPORT_SYMBOL, module param, module signing, out-of-tree