Linuxカーネルモジュールの管理:modprobe、lsmod、DKMSのプロ向けガイド

Linux tutorial - IT technology blog
Linux tutorial - IT technology blog

見えないハードウェアの謎

Mellanox의 10GbEネットワークカードやハイエンドのNVMeコントローラーをインストールしたばかりなのに、ip linklsblkを実行しても何も表示されないことがあります。ハードウェアは物理的に装着され、LEDも点滅しているのに、オペレーティングシステムからはまるで見えないかのように振る舞います。これは通常、ハードウェアの故障ではありません。むしろ、カーネルモジュールが不足しているか、休止状態にあるときによく見られる典型的な兆候です。

Linuxはモジュール型設計を採用しています。カーネルモジュール(.koファイル)は、システムの完全な再起動を必要とせずに、オンザフライで機能を追加するプラグインのようなものだと考えてください。これらのモジュールがロードに失敗したり、定期的なapt upgradeの後にドライバーが壊れたりすると、システムのパフォーマンスと安定性は即座に危険にさらされます。

モジュール式カーネルの内部

なぜすべてをカーネルに直接組み込まないのでしょうか?もし、1991年以降に製造されたすべてのハードウェア用ドライバーをvmlinuzイメージに直接コンパイルしたとしたら、カーネルは巨大なものになってしまいます。所有すらしていないハードウェアをサポートするためだけに、数百メガバイトものRAMを占有することになるでしょう。代わりに、カーネルはスリムな状態を保ち、その環境に必要な特定のコードだけをロードします。

lsmodによるシステムの監査

設定を変更し始める前に、現在何が動作しているかを確認する必要があります。lsmodコマンドは、/proc/modulesからデータを取得し、アクティブなスタックを表示します。一般的なUbuntuサーバー環境では、常時80から120個のモジュールがロードされているのが普通です。

lsmod | head -n 10

出力には、「Module(モジュール)」、「Size(サイズ)」、「Used by(使用元)」の3つの列が表示されます。「Used by」のカウントには細心の注意を払ってください。カウントがゼロではないモジュールをアンロードしようとすると、システムクラッシュやカーネルパニックを即座に防ぐために、カーネルはその要求をブロックします。

modinfoで詳細を調査する

overlayiwlwifiのような、目的が曖昧なモジュール名に遭遇したときは、推測に頼ってはいけません。modinfoを使用して調査します。

modinfo iwlwifi

このコマンドは、開発者、ライセンス、そして最も重要な「利用可能なパラメータ」をリストアップします。例えば、IntelのWi-Fi接続が頻繁に切れる場合、modinfopower_saveパラメータを見つけ、リンクを安定させるためにそれを切り替えるといった対処が可能になります。

modprobeによるアクティブな管理

歴史的に、管理者はinsmodrmmodを使用してきました。しかし、これらのツールは依存関係を理解できないため「不器用」です。モジュールAが機能するためにモジュールBを必要とする場合、insmodは単にエラーを返します。modprobeは依存関係チェーン全体を自動的に処理するため、現代の標準となっています。

オンザフライでのロードとアンロード

実行中のカーネルにモジュールとその依存関係を注入するには、次のように入力します。

sudo modprobe [module_name]

安全に削除するには、次のようにします。

sudo modprobe -r [module_name]

本番環境では効率が重要です。私が4GBのRAMを搭載したUbuntu 22.04インスタンスで高トラフィックのWebゲートウェイをチューニングした際、floppybluetoothjoydevなどの未使用モジュールを削ぎ落としました。これにより、カーネルのメモリフットプリントが約120MB削減され、割り込みレイテンシもわずかに改善しました。

依存関係の更新

modprobemodules.depに依存しています。ドライバーを手動でコンパイルしたり、.koファイルを移動したりした場合、マップを更新するまでmodprobeはそれらを見つけることができません。sudo depmod -aを実行して、カーネルに利用可能なモジュールを再インデックスさせ、パスの問題を修正します。

永続化とブラックリスト化

手動でのmodprobeコマンドは一時的なもので、再起動すると消えてしまいます。システムが起動するたびにドライバーをロードさせるには、その名前を/etc/modulesに追加するか、/etc/modules-load.d/に専用の設定ファイルを作成します。

# テスト用にdummyネットワークインターフェースを強制的にロードする
echo "dummy" | sudo tee /etc/modules-load.d/dummy.conf

問題のあるドライバーの除外

競合はよくあることで、特にグラフィックス関連で顕著です。オープンソースのnouveauドライバーは、プロプライエタリなNVIDIAドライバーとしばしば競合します。モジュールのロードを完全に阻止するには、/etc/modprobe.d/でブラックリストに登録する必要があります。

# ブラックリストファイルを作成する
sudo nano /etc/modprobe.d/blacklist-nouveau.conf

# 次の行を追加する:
blacklist nouveau
options nouveau modeset=0

これらのファイルを変更した後は、sudo update-initramfs -uを実行しなければなりません。これにより、カーネルがルートファイルシステムをマウントする前の初期ブート環境にブラックリストが確実に組み込まれます。

DKMSによる再ビルドの自動化

カーネルのセキュリティパッチによってサードパーティのドライバーが壊れることほど、稼働時間を損なうものはありません。ZFS、VirtualBox、または特殊なRAIDドライバーなどの「アウトオブツリー(out-of-tree)」ドライバーを使用している場合、それらは特定のカーネルバージョンに紐付けられています。カーネルバージョンが変わると、ドライバーは動作しなくなります。

Dynamic Kernel Module Support (DKMS) はその解決策です。新しいカーネルがインストールされたことを検出し、新しいヘッダーに対してドライバーを自動的に再コンパイルします。これにより、手動で20分かかるコンパイル作業が、apt upgrade中にバックグラウンドで行われるプロセスに変わります。

現在のDKMSのステータスを確認するには、次のようにします。

dkms status

モジュールが「added」状態のまま停止している場合は、手動でビルドを強制できます。

sudo dkms install -m [module_name] -v [version]

カーネルリングバッファによるトラブルシューティング

modprobeが「Operation not permitted(許可されていない操作)」という曖昧なエラーで失敗した場合、真の答えはカーネルリングバッファに隠されています。dmesgを使用して、カーネルが何に対して不満を言っているのかを正確に確認します。

sudo dmesg | grep -i [module_name] | tail -n 20

以下の3つのレッドフラグ(警告サイン)を探してください:

  • Unknown symbol(シンボル不明): モジュールがおそらく異なるカーネルバージョン用にコンパイルされています(DKMSのステータスを確認してください)。
  • Signature failure(署名の失敗): UEFI Secure Bootが有効になっており、カスタムモジュールをMOK(Machine Owner Key)で署名していません。
  • Missing firmware(ファームウェアの欠如): モジュールはロードされましたが、/lib/firmware内にあるはずのバイナリブロブを探して見つからない状態です。

lsmodmodprobe、そしてdkmsをマスターすることで、Linuxカーネルは神秘的な「ブラックボックス」から、管理可能で透明性の高いインフラの一部へと変わります。

Share: