LPIC201対策 - Linuxカーネルのコンパイル

# この記事について

Linux Level 2 取得を目標としている筆者です。
先日 Level 1 を取得しましたが、短期詰め込みの暗記がしんどかったので、Level2はじっくり時間をかけていいから、ちゃんと理解してやっていきたい。

一方で、暗記も暗記で重要。

ということで、理解を深めるためにと、暗記しやすいように、両方の目的で、覚えたことを Qiita に整理してまとめながら受験対策することにしました。

# この分野で覚えること

## ファイル・ディレクトリ関連

### /usr/src/linux 配下

`/usr/src/linux/` は、カーネルのソースやビルドに必要なディレクトリ・ファイルを置いてあるディレクトリです。

| ディレクトリ | 中身(格納しているもの) |
|:-|:-|
|kernel/ |カーネル本体の**ソース**|
|Documentation/|カーネルのビルドやインストール時に参照する資料|
|arch/|アーキテクチャ（x86_64, i386など）固有のコード|
|drivers/|デバイスドライバ|
|fs/|ファイルシステム|
|include/|インクルードファイル（他のファイルから呼び出すコードのまとまり）|
|mm/|メモリ管理|
|net/|ネットワーク|


| ファイル | 中身 |
|:-|:-|
|.config|カーネルをビルドするための各種設定（make config や make menuconfig で行った**実際に行った設定**を保存）|
|Makefile |makeコマンドの**動作**やカーネルのバージョンを記述|

### /boot 配下

|ファイル|中身|詳細|
|:-|:-|:-|
|/boot/System.map-x.x.x|カーネルのアドレスマップ|カーネルがメモリ上に展開される際、シンボルとアドレスのマッピングを記述したファイル|
|/boot/vmlinuz-x.x.x|カーネルイメージファイル|zImage形式と、bzImage形式がある|
|/boot/config-x.x.x|ビルド時のカーネル設定|- `/usr/src/linux/.config` のバックアップ<br>- `make oldconfig` で読み込む「現在動いているカーネルの設定」はこれ|
|/boot/initrd.img-x.x.x|初期RAMディスクイメージ||

### その他

| ディレクトリ | 中身 |
|:-|:-|
|/lib/modules/x.x.x/| カーネルモジュールのインストール先|

:::note warn
個人的に、/bin/ とよく間違える。カーネル**モジュール**なので lib。
:::

## 初期RAMディスクについての基本知識

### 初期RAMディスクとは

システムの起動時に、ブートプロセスを段階的に行うために使われる。

古いディストリビューションでは `initrd` 形式が使われていたが、最近のディストリビューションでは `initramfs` 形式が主流になっている。

:::note warn
しかしGRUB2の設定ファイルでは、起動時に使用する初期RAMディスクのイメージファイルを指定する項目の項目名は initrd になっている。。。
:::

### 作成コマンド

#### dracut

#### mkinitrd

- gunzip と mount コマンドで中身を参照できる

#### mkinitramfs

- cpioアーカイブを利用して初期RAMディスクを作成

```shell
### 初期RAMディスク（バージョン x.x.x）を作成
# mkinitramfs -o initrd.img.gz x.x.x

# ls
initrd.img.gz

### gunzipで解凍
# gunzip initrd.img.gz
initrd.img

### cpio を使って書き出し
cpio -id < initrd.img

##### cpiokomando のオプション解説
### -i コピーインモード（アーカイブからの展開）
### -d ディレクトリを作成

# ls
bin/ conf/ etc ... # など、initrd.img から展開されたディレクトリができている

```

以下の要領で実行（/boot/initrd.img は作成先）
`mkinitramfs -o /boot/initrd.img x.x.x`

## make コマンド

### そもそも make コマンドとは

make コマンド自体は、ソースファイルをコンパイルするための一般的なコマンドだが、これを使ってカーネルをコンパイルすることができる。

コマンド実行時の手順は、 `/usr/src/linux/Makefile` の記述に従う。

試験対策上は、このコマンドのターゲット（サブコマンド的なもの？）がよく出題されるようなので以下に整理。

初期化 → 設定 →　ビルド →　配置（インストール）のじゅんに行うよ。

### make コマンドのターゲット

#### 削除系

まずはこれをたたいて設定を初期化する。

| ターゲット | 意味 |
|:-|:-|
|clean| 設定ファイル(.config)を**除いて**一時ファイル等を削除|
|mrproper| 設定ファイル(.config)を**含めて**一時ファイル等を削除|

#### config (設定ファイルの作成) 系

次にこれをたたいて、設定ファイルを作成

| ターゲット | 意味 |
|:-|:-|
|config|対話的に設定を実施|
|menuconfig| ターミナル上のGUIで設定|
|xconfig| X上のGUIで設定|
|deconfig| デフォルト状態の設定ファイルを作成|
|oldconfig| 現在動いているカーネルの設定を引き継いだ設定ファイルを作成|

#### ビルド系

設定ファイルに基づきビルド

| ターゲット | 意味 |
|:-|:-|
|all |カーネル本体およびカーネルモジュールをビルド<br>（ターゲットなしと同じ）|
|modules |カーネル本体は含めずカーネルモジュールをビルド|

#### install (配置) 系

そして配置。
通常は `modules_install` でカーネルモジュールを配置してから、 `install` でカーネル本体をインストールする。

| ターゲット | 意味 |
|:-|:-|
|modules_install |カーネルモジュールをシステムに適切に配置|
|install |ビルドしたカーネルの本体をシステムに適切に配置|

##### 配置とは具体的にどういうことなのか

以下をうまいことやってくれるそうです

- ビルドされたカーネルを /boot に移動
- ファイル名（カーネルイメージ等）にバージョンをつけてリネーム
- ブートローダに新しいカーネルを使った起動設定を追加
- （必要な場合）初期RAMディスクのイメージを作成

カーネルモジュールは最終的には `/lib/modules/x.x.x/` に置く。modules_install を使うと、ここまでやってくれる。

古いカーネルイメージは、バックアップとして残しておくことが推奨。（makeコマンドで勝手に消されることもない）

#### pkg (パッケージ作成) 系

| ターゲット | 意味 |
|:-|:-|
|binrpm-pkg |ソースを含まないrpmパッケージを作る|
|rpm-pkg |ソースを含むrpmパッケージを作る|
|deb-pkg |ビルド済みDebianパッケージを作る|


## その他の暗記事項

| 用語 | 意味 |
|:-|:-|
|DKMS| Dynamic Kernel Management System。カーネルのアップグレード時に、自動的にカーネルモジュールをリビルドできる。|

### カーネルのバージョンの読み方

- 2.6より前
    - x.y.z の y 部分が奇数だと開発版、偶数だと安定版
- 2.6以降
    - 上記の区別なし。単純にハイフンや記号がついていなければ安定版

### カーネルのリリースサイクル

以下のカテゴリを、順に格上げしていく

| カテゴリ | 意味 |
|:-|:-|
|prepatch|リリース候補（RC）。テストが必要な新機能が含まれている。 |
|mainline|リーナス・トーヴァルズ氏が数ヶ月ごとにリリースする安定版。（リリースされた時点で、安定版の第0版とみなされる |
|stable|mainlineの後にリリースされる安定版（mainlineの不具合の修正など） |
|longterm|stableの中から選ばれ、約2年間という長期にわたってバグフィックスが行われる |


# 以上！

勉強が進んだら適宜追記・修正などしていきます。