Linuxカーネルを再構築してみた(5.14.0→6.7.0)

## はじめに
Linuxの勉強のためにカーネルを再構築してみたので、備忘録をかねてそのときに実行したコマンドをまとめます。<br>
作業環境はAlmaLinuxというRedHat系のディストリビューションです。

## 実行コマンド
まずは今のカーネルのバージョンを確認しておきます。
そしてカーネル再構築のためにrootユーザーになります。<br><br>
```
# 現在のカーネルのバージョンを確認
[user@localhost ~]$ uname -r
5.14.0-362.8.1.el9_3.x86_64
[user@localhost ~]$ sudo su -
```
<br>
続いて以下のページを参考に必要なツールをインストール。

https://qiita.com/tutuz/items/f824475d00b35dd39e6b#1-1%E9%96%8B%E7%99%BA%E3%83%84%E3%83%BC%E3%83%AB%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB

<br>

```
[root@localhost ~]# yum groupinstall "Development Tools"
[root@localhost ~]# yum install kernel-devel
[root@localhost ~]# yum install rpm-build redhat-rpm-config
[root@localhost ~]# yum install ncurses ncurses-devel
```
<br>
さらにカーネルソースを以下のサイトを参考にダウンロードします。

https://www.kernel.org/

カーネルソースは慣例的に`/usr/src`に配置するらしいので郷に従います。<br><br>

```
[root@localhost ~]# cd /usr/src
# 最新版(2024/01/15時点)のLinux6.7をダウンロード
[root@localhost src]# wget https://mirrors.edge.kernel.org/pub/linux/kernel/v6.x/linux-6.7.tar.xz
```

<br>

ダウンロードしたカーネルソースを展開します。
展開前のファイルは不要ですが念のため`/tmp`に残しておきます。<br><br>

```
[root@localhost src]# xz -dc linux-6.7.tar.xz | tar xvf -
[root@localhost src]# mv linux-6.7.tar.xz /tmp/linux-6.7.tar.xz
```

<br>

次に、カーネルコンフィギュレーションに新しい設定を追加します。<br>
現在の設定ファイル（/boot/config-5.14.0-362.8.1.el9_3.x86_64）を.configファイルにコピーし、`make oldconfig`コマンドで新たな設定を反映させます。<br>
`make oldconfig`コマンドを実行すると、いくつか設定について選択が求められます。<br>
今回はすべてデフォルトの設定（選択するときに何も選ばず`Enter`キーを押下）にします。<br><br>

```
[root@localhost src]# cp /boot/config-5.14.0-362.8.1.el9_3.x86_64 .config
# make oldconfigコマンドを実行するために展開したカーネルソースのディレクトリに移動
[root@localhost src]# cd linux-6.7/
[root@localhost linux-6.7]# make oldconfig
  HOSTCC  scripts/basic/fixdep
  HOSTCC  scripts/kconfig/conf.o
  HOSTCC  scripts/kconfig/confdata.o
  HOSTCC  scripts/kconfig/expr.o
  LEX     scripts/kconfig/lexer.lex.c
  YACC    scripts/kconfig/parser.tab.[ch]
  HOSTCC  scripts/kconfig/lexer.lex.o
  HOSTCC  scripts/kconfig/menu.o
  HOSTCC  scripts/kconfig/parser.tab.o
  HOSTCC  scripts/kconfig/preprocess.o
  HOSTCC  scripts/kconfig/symbol.o
  HOSTCC  scripts/kconfig/util.o
  HOSTLD  scripts/kconfig/conf
#
# using defaults found in /boot/config-5.14.0-362.8.1.el9_3.x86_64
#
.config:428:warning: symbol value 'm' invalid for I8K
.config:7913:warning: symbol value 'm' invalid for CRYPTO_BLAKE2S_X86
*
* Restart config...
*
*
* Timers subsystem
*
Timer tick handling
  1. Periodic timer ticks (constant rate, no dynticks) (HZ_PERIODIC)
  2. Idle dynticks system (tickless idle) (NO_HZ_IDLE)
> 3. Full dynticks system (tickless) (NO_HZ_FULL)
choice[1-3?]: 3
Force user context tracking (CONTEXT_TRACKING_USER_FORCE) [N/y/?] n
Old Idle dynticks config (NO_HZ) [Y/n/?] y

・・・（中略）・・・

Microsoft Hyper-V driver testing (HYPERV_TESTING) [N/y/?] n
#
# configuration written to .config
#
```

<br>

続いてカーネルとカーネルモジュールをコンパイルします。
以下のサイトを参考に事前に.configファイルを修正しておきます。

https://qiita.com/OPySPGcLYpJE0Tc/items/f0120d7274216172aedc

<br>

```
[root@localhost linux-6.7]# vi .config
# 修正1
CONFIG_SYSTEM_TRUSTED_KEYS="certs/rhel.pem"
↓
CONFIG_SYSTEM_TRUSTED_KEYS=""
# 修正2
CONFIG_DEBUG_INFO_BTF=y
↓
CONFIG_DEBUG_INFO_BTF=n
```

<br>

`make`コマンドでカーネルとカーネルモジュールをコンパイルします。
少しでも実行時間を短くするため、`-j`オプションで並列実行します。<br><br>

```
# CPUのコア数確認
[root@localhost linux-6.7]# cat /proc/cpuinfo | grep "cpu core"
cpu cores	: 2
cpu cores	: 2
cpu cores	: 2
cpu cores	: 2
# 「make」コマンドでカーネルとカーネルモジュールをコンパイル
# -jオプションで並列実行
# 並列実行数はCPUのCore数＋1にする（理由は不明）
[root@localhost linux-6.7]# make -j 3
```
<br>

そしてカーネルモジュールとカーネルをインストールします。<br><br>

```
[root@localhost linux-6.7]# make modules_install
[root@localhost linux-6.7]# make install
# /bootディレクトリ以下に追加されているか確認
[root@localhost linux-6.7]# ls /boot

・・・（中略）・・・

vmlinuz-0-rescue-ad6108d8fa2d4e86b2104b3c2d335169
vmlinuz-5.14.0-362.8.1.el9_3.x86_64
vmlinuz-6.7.0
```
<br>

`/boot`の末尾に新たに`vmlinuz-6.7.0`が追加されていることがわかります。
あとはリブートを行い、カーネルが更新されているか確認するだけです。<br><br>

```
[root@localhost linux-6.7]# reboot
[user@localhost ~]$ uname -r
6.7.0
```

<br>

無事にカーネルが更新されました。
デフォルトのカーネルが更新されているかも確認しておきます。<br><br>

```
# 念のためデフォルトのカーネルが更新されているか確認
[hiroaki@localhost ~]$ sudo su -
[root@localhost ~]# grubby --default-kernel
/boot/vmlinuz-6.7.0
```

<br>

補足としてこれまで使ってきたバージョンのカーネルに戻したい場合のコマンドも以下にまとめておきます。<br><br>

```
# 各カーネルのindexを確認
[root@localhost ~]# grubby --info=ALL | grep -A 2 index
index=0
kernel="/boot/vmlinuz-6.7.0"
args="ro resume=/dev/mapper/almalinux-swap rd.lvm.lv=almalinux/root rd.lvm.lv=almalinux/swap rhgb quiet crashkernel=1G-4G:192M,4G-64G:256M,64G-:512M $tuned_params"
--
index=1
kernel="/boot/vmlinuz-5.14.0-362.8.1.el9_3.x86_64"
args="ro resume=/dev/mapper/almalinux-swap rd.lvm.lv=almalinux/root rd.lvm.lv=almalinux/swap rhgb quiet $tuned_params"
--
index=2
kernel="/boot/vmlinuz-0-rescue-ad6108d8fa2d4e86b2104b3c2d335169"
args="ro resume=/dev/mapper/almalinux-swap rd.lvm.lv=almalinux/root rd.lvm.lv=almalinux/swap rhgb quiet"
# 以下のコマンドの「n」に更新したいカーネルのindexの番号を記入
[root@localhost ~]# grubby --set-default-index=n
```
## おわりに
今回はLinuxカーネルを再構築してみました。
Linuxを学んでいる方の参考になれば幸いです。<br>
最後まで読んでいただき、ありがとうございました！