Ubuntuにはいくつかのカーネルヴァリアントが用意されています。今回はこのカーネルヴァリアントがどういうものかを解説し、具体的なカーネルヴァリアントを取り上げてカーネルコンフィグ上の違いを確認する方法を紹介します。また、応用的な内容としてWSL2用のカーネルについてもカーネルコンフィグを見てみます。
カーネルヴァリアント
Ubuntuでは特定の環境やユースケースなどに合わせてチューニング・
本連載やUbuntu Weekly Topicsの読者の中には
なぜカーネルヴァリアントが必要なのか
ISOイメージ等を使いお手元のPCにUbuntuをインストールする場合、デフォルトではバージョンにgeneric
と入っているカーネルがインストールされるはずです。これもカーネルヴァリアントの1つですがgeneric
とある通り、
ここにカーネルヴァリアントの存在意義があります。例えば、パブリッククラウドやRaspberry Piといった環境ではハードウェア構成が一定の範囲に収まるため、使われないであろうカーネルの設定を無効にしたり、反対にハードウェア構成に合わせて設定をチューニングしたりすることで最適化できます。
また、特定のユースケース向け、具体的にはレイテンシーセンシティブなユースケースではリアルタイムカーネルlowlatency
カーネル)
バージョン違いのカーネルヴァリアントにはHardware Enablement = HWEカーネルがあります。まず、UbuntuのLTSがリリースされる際に同梱されているカーネルはGeneral Availability = GAカーネルと呼ばれます。それと対比されるのがこのHWEカーネルで、簡単に言えば
カーネルコンフィグ
カーネルの実際の設定についてはコンフィグファイルを見ることで確認できます。システムにインストールされているカーネルのコンフィグファイルは/boot/
linux-modules-6.
というパッケージであることがわかります。
$ dpkg -S /boot/config-6.8.0-45-generic linux-modules-6.8.0-45-generic: /boot/config-6.8.0-45-generic
このファイルを開くと(設定項目)=(設定値)
といった形式でカーネルのコンフィグが記述されています。デバイスドライバーの状況もここから読み取ることができ、設定値がy
のドライバーはカーネル本体に組み込まれており、そのカーネルを使ってシステムを起動すると問答無用でドライバーも読み込まれます。m
となっているものは必要に応じて脱着できるようにカーネルモジュールとして提供されます。n
もしくは設定がないものについてはそのどちらでもなく、カーネルのコンフィグとしてはドライバーを用意しない状態となります。
設定値がy
, m
のものについて、それぞれ実際に確認してみましょう。
カーネルコンフィグを見比べてみる
それではカーネルヴァリアント間でカーネルコンフィグを見比べてみます。今回はgeneric
カーネルとlowlatency
カーネルを見比べます。具体的には、前述の通り、カーネルコンフィグは/boot/
のconfig-
から始まるファイルに記載されているため、これを入手しdiffを取ってしまうことにします。なお、ここではUbuntu24.6.
のx86_
/boot/
のconfig-
から始まるファイルはlinux-modules
パッケージで提供されているため、lowlatency
カーネルに対応するlinux-modules
パッケージを入手します。
$ apt download linux-modules-6.8.0-45-lowlatency
ダウンロードが完了するとlinux-modules-6.
というパッケージファイルがカレントディレクトリに置かれます。これをlinux-modules-6.
というディレクトリに展開します。
$ dpkg-deb -x linux-modules-6.8.0-45-lowlatency_6.8.0-45.45.1_amd64.deb linux-modules-6.8.0-45-lowlatency
これにより./
にカーネルコンフィグファイルが展開・config-6.
を入手できましたので、/boot/
と内容を比較します。
$ diff -u /boot/config-6.8.0-45-generic ./linux-modules-6.8.0-45-lowlatency/boot/config-6.8.0-45-lowlatency
--- /boot/config-6.8.0-45-generic 2024-08-30 17:32:37.000000000 +0900
+++ ./linux-modules-6.8.0-45-lowlatency/boot/config-6.8.0-45-lowlatency 2024-09-02 22:14:44.000000000 +0900
@@ -50,7 +50,7 @@
CONFIG_KERNEL_ZSTD=y
CONFIG_DEFAULT_INIT=""
CONFIG_DEFAULT_HOSTNAME="(none)"
-CONFIG_VERSION_SIGNATURE="Ubuntu 6.8.0-45.45-generic 6.8.12"
+CONFIG_VERSION_SIGNATURE="Ubuntu 6.8.0-45.45.1-lowlatency 6.8.12"
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_SYSVIPC_COMPAT=y
@@ -131,8 +131,8 @@
CONFIG_PREEMPT_BUILD=y
# CONFIG_PREEMPT_NONE is not set
-CONFIG_PREEMPT_VOLUNTARY=y
-# CONFIG_PREEMPT is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
CONFIG_PREEMPT_COUNT=y
CONFIG_PREEMPTION=y
CONFIG_PREEMPT_DYNAMIC=y
@@ -170,7 +170,7 @@
CONFIG_RCU_STALL_COMMON=y
CONFIG_RCU_NEED_SEGCBLIST=y
CONFIG_RCU_NOCB_CPU=y
-# CONFIG_RCU_NOCB_CPU_DEFAULT_ALL is not set
+CONFIG_RCU_NOCB_CPU_DEFAULT_ALL=y
CONFIG_RCU_LAZY=y
CONFIG_RCU_LAZY_DEFAULT_OFF=y
# end of RCU Subsystem
ここから、generic
カーネルに対してlowlatency
カーネルには次の差分があることがわかります。
CONFIG_
がオフPREEMPT_ VOLUNTARY ( is not set
)となっている代わりに CONFIG_
がオンPREEMPT ( y
)になっている CONFIG_
がオフRCU_ NOCB_ CPU_ DEFAULT_ ALL ( is not set
)からオン ( y
)になっている
これらはどういうものなのでしょうか。調べる方法の1つにLKDDbのようなツールを使う方法があります。ここから見つかればこれを使うのが簡単です。
検索をかけてみると次のように情報が見つかりました。
CONFIG_
: https://PREEMPT_ VOLUNTARY cateee. net/ lkddb/ web-lkddb/ PREEMPT_ VOLUNTARY. html CONFIG_
: https://PREEMPT cateee. net/ lkddb/ web-lkddb/ PREEMPT. html CONFIG_
: https://RCU_ NOCB_ CPU_ DEFAULT_ ALL cateee. net/ lkddb/ web-lkddb/ RCU_ NOCB_ CPU_ DEFAULT_ ALL. html
本稿ではこれらの差分による詳細な動作の違いには踏み込みませんが、CONFIG_
については、ブログ記事があります。この記事にある通りlowlatency
ヴァリアントカーネルでは低レイテンシーを達成するために、プリエンプションに関してよりシビアな設定となっていることがわかりました。逆に言えば、これら3つ以外はgeneric
カーネルと設定値に違いはないこともわかります。[2]
このようにgeneric
カーネルと他のカーネルヴァリアントとを同じように比較してみると、ヴァリアントごとに具体的にどういうチューニングが入っているのかを確認できます。
WSL2のカーネルについて調べる
カーネルコンフィグの読み方・
前提として、WSL2で提供されるカーネルはMicrosoft がビルド・
つまり、WSL2用のカーネルは
「では、同じように/boot
の下にあるコンフィグファイルを確認して……」/boot
の中身は空っぽです[3]。Ubuntuのレポジトリから提供されているカーネルでもないのでパッケージから抽出しようにもパッケージがありません。そのため、別のやり方でカーネルコンフィグを確認する必要があります。
WSL2用のカーネルのソースコードはGibHub上のWSL2-Linux-Kernelレポジトリで管理されています。また、このレポジトリに含まれるREADME.make KCONFIG_
を実行してカーネルをビルドせよ」Microsoft/
のコンフィグ内容でビルドされているはずであるという推測が成立します。
続いて、PowerShellやコマンドプロンプトからwsl --version
コマンドで確認すると、本稿執筆時点で最新のWSLバージョンは2.Microsoft/
は../
へのシンボリックリンクになっています。ここから、今回確認してみたいWSL2カーネルバージョン5.
WSL2用のカーネルは前述のとおり、本来の意味でのカーネルヴァリアントではないことから、generic
カーネルなどと比較しても有意義ではないためdiffを取ってみることはしません。ただ、非常に大雑把な指標ですが、有効となっているy
やm
と指定されている)generic
カーネルと比較してみると、WSL2用のカーネルは有効な設定がかなり絞り込まれていることがうかがえます。
$ wget https://raw.githubusercontent.com/microsoft/WSL2-Linux-Kernel/refs/tags/linux-msft-wsl-5.15.153.1/arch/x86/configs/config-wsl $ grep -e =[ym] /boot/config-6.8.0-45-generic |wc -l 9351 $ grep -e =[ym] config-wsl |wc -l 1416
その一方で、WSL2はHyper-V のアーキテクチャを利用しているため、Hyper-VのゲストOSとして必要なモジュール
$ grep HYPERV_ /boot/config-6.8.0-45-generic # genericカーネルでのHyper-V関連のコンフィグ CONFIG_HYPERV_VSOCKETS=m CONFIG_PCI_HYPERV_INTERFACE=m CONFIG_HYPERV_STORAGE=m CONFIG_HYPERV_NET=m CONFIG_HYPERV_KEYBOARD=m CONFIG_HID_HYPERV_MOUSE=m # CONFIG_HYPERV_VTL_MODE is not set CONFIG_HYPERV_TIMER=y CONFIG_HYPERV_UTILS=m CONFIG_HYPERV_BALLOON=m CONFIG_HYPERV_IOMMU=y # CONFIG_HYPERV_TESTING is not set $ grep HYPERV_ config-wsl #WSL2用カーネルでのHyper-V関連のコンフィグ CONFIG_HYPERV_VSOCKETS=y CONFIG_PCI_HYPERV_INTERFACE=y CONFIG_HYPERV_STORAGE=y CONFIG_HYPERV_NET=y CONFIG_HYPERV_KEYBOARD=y # CONFIG_HID_HYPERV_MOUSE is not set CONFIG_HYPERV_TIMER=y CONFIG_HYPERV_UTILS=y CONFIG_HYPERV_BALLOON=y # CONFIG_HYPERV_IOMMU is not set # CONFIG_HYPERV_TESTING is not set
なお、GitHub上のリリース情報を確認すると、WSLバージョン2.
WSLバージョン2.