3.11. カスタムカーネルモジュールのコンパイル

ハードウェアおよびソフトウェアレベルで、さまざまな設定による要求に応じて、サンプリングカーネルモジュールを構築できます。

前提条件

  • kernel-devel パッケージ、gcc パッケージ、および elfutils-libelf-devel パッケージをインストールしている。

    # dnf install kernel-devel-$(uname -r) gcc elfutils-libelf-devel
  • root 権限がある。
  • カスタムカーネルモジュールをコンパイルする /root/testmodule/ ディレクトリーを作成している。

手順

  1. 以下の内容で /root/testmodule/test.c を作成します。

    #include <linux/module.h>
    #include <linux/kernel.h>
    
    int init_module(void)
        { printk("Hello World\n This is a test\n"); return 0; }
    
    void cleanup_module(void)
        { printk("Good Bye World"); }
    
    MODULE_LICENSE("GPL");

    test.c ファイルは、カーネルモジュールに主な機能を提供するソースファイルです。このファイルは、組織的な目的で、専用の /root/testmodule/ ディレクトリーに作成されています。モジュールをコンパイルすると、/root/testmodule/ ディレクトリーには複数のファイルが含まれます。

    test.c ファイルには、システムライブラリーから次のものが含まれます。

    • サンプルコードの printk() 機能には、linux/kernel.h ヘッダーファイルが必要です。
    • linux/module.h ファイルには、C 言語で記述した複数のソースファイルで共有する関数宣言とマクロ定義が含まれています。
  2. 次に、init_module() 関数および cleanup_module() 関数に従い、テキストを出力するカーネルロギング機能 printk() を起動および終了します。
  3. 以下の内容で /root/testmodule/Makefile を作成します。

    obj-m := test.o

    Makefile には、コンパイラーが、test.o という名前のオブジェクトファイルを作成する必要がある指示が含まれています。obj-m ディレクティブは、生成される test.ko ファイルを、読み込み可能なカーネルモジュールとしてコンパイルすることを指定します。もしくは、obj-y ディレクティブは、組み込みカーネルモジュールとして test.ko をビルドするように指示します。

  4. カーネルモジュールをコンパイルします。

    # make -C /lib/modules/$(uname -r)/build M=/root/testmodule modules
    make: Entering directory '/usr/src/kernels/5.14.0-70.17.1.el9_0.x86_64'
      CC [M]  /root/testmodule/test.o
      MODPOST /root/testmodule/Module.symvers
      CC [M]  /root/testmodule/test.mod.o
      LD [M]  /root/testmodule/test.ko
      BTF [M] /root/testmodule/test.ko
    Skipping BTF generation for /root/testmodule/test.ko due to unavailability of vmlinux
    make: Leaving directory '/usr/src/kernels/5.14.0-70.17.1.el9_0.x86_64'

    コンパイラーは、各ソースファイル (test.c) のオブジェクトファイル (test.o) を中間手順として作成してから、それらを最終カーネルモジュール (test.ko) にリンクします。

    コンパイルが成功すると、/root/testmodule/ には、コンパイル済みカスタムカーネルモジュールに関連する追加ファイルが含まれます。コンパイル済みモジュール自身は、test.ko ファイルで表されます。

検証

  1. 必要に応じて、/root/testmodule/ ディレクトリーのコンテンツを確認します。

    # ls -l /root/testmodule/
    total 152
    -rw-r—​r--. 1 root root    16 Jul 26 08:19 Makefile
    -rw-r—​r--. 1 root root    25 Jul 26 08:20 modules.order
    -rw-r—​r--. 1 root root     0 Jul 26 08:20 Module.symvers
    -rw-r—​r--. 1 root root   224 Jul 26 08:18 test.c
    -rw-r—​r--. 1 root root 62176 Jul 26 08:20 test.ko
    -rw-r—​r--. 1 root root    25 Jul 26 08:20 test.mod
    -rw-r—​r--. 1 root root   849 Jul 26 08:20 test.mod.c
    -rw-r—​r--. 1 root root 50936 Jul 26 08:20 test.mod.o
    -rw-r—​r--. 1 root root 12912 Jul 26 08:20 test.o
  2. カーネルモジュールを /lib/modules/$(uname -r)/ ディレクトリーにコピーします。

    # cp /root/testmodule/test.ko /lib/modules/$(uname -r)/
  3. モジュールの依存関係のリストを更新します。

    # depmod -a
  4. カーネルモジュールを読み込みます。

    # modprobe -v test
    insmod /lib/modules/5.14.0-1.el9.x86_64/test.ko
  5. カーネルモジュールが正常に読み込まれたことを確認します。

    # lsmod | grep test
    test                   16384  0
  6. カーネルリングバッファーから最新のメッセージを読み込みます。

    # dmesg
    [74422.545004] Hello World
                    This is a test