8
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

FreeBSDカーネル開発シリーズ

Part1 ビルド Part2 モジュール Part3 ドライバ Part4 システムコール Part5 DTrace
👈 Now - - - -

はじめに

Linuxのカーネルビルドはやったことある人多いと思う。

でもFreeBSDのカーネルビルドはやったことある?

実はFreeBSDの方がLinuxよりカーネル開発に入りやすいんだよ。理由:

  • ソースツリーがシンプル
  • ドキュメントが充実
  • カーネルとユーザーランドが一体で開発されてる

今回はカーネルのビルドから改造まで、ハンズオン形式で解説する。

ソースコードの取得

Gitでクローン

pkg install git

# 安定版(14.2-RELEASE)
git clone --branch releng/14.2 --depth 1 https://git.FreeBSD.org/src.git /usr/src

# 開発版(main)
git clone --depth 1 https://git.FreeBSD.org/src.git /usr/src

ソースツリーの構造

/usr/src/
├── bin/            # 基本コマンド (/bin/ls等)
├── sbin/           # システムコマンド (/sbin/mount等)
├── usr.bin/        # ユーザーコマンド (/usr/bin/*)
├── usr.sbin/       # システム管理コマンド
├── lib/            # ライブラリ
├── sys/            # ★カーネルソース★
│   ├── amd64/      # x86_64アーキテクチャ依存
│   ├── arm64/      # ARM64アーキテクチャ依存
│   ├── conf/       # カーネル設定ファイル
│   ├── dev/        # デバイスドライバ
│   ├── fs/         # ファイルシステム
│   ├── kern/       # カーネルコア
│   ├── net/        # ネットワーク
│   ├── vm/         # 仮想メモリ
│   └── ...
├── share/          # 共有データ
├── contrib/        # サードパーティソース
└── Makefile        # トップレベルMakefile

Linuxと比べてシンプル。全部が1つのリポジトリに入ってる。

カーネルの設定

設定ファイル

cd /usr/src/sys/amd64/conf/
ls
# GENERIC  GENERIC.hints  MINIMAL  NOTES
  • GENERIC: 標準的なカーネル設定
  • MINIMAL: 最小構成
  • NOTES: 全オプションの説明

カスタム設定の作成

cp GENERIC MYKERNEL
vi MYKERNEL
# カーネル名を変更
ident           MYKERNEL

# 不要なドライバを削除してスリム化
nodevice        fdc          # フロッピーディスク
nodevice        ata          # IDE/ATA
nodevice        isci         # Intel SAS

# デバッグオプション追加
options         KDB          # カーネルデバッガ
options         DDB          # 対話型デバッガ
options         GDB          # リモートGDB
options         INVARIANTS   # 追加のアサーション
options         INVARIANT_SUPPORT

# DTrace有効化
options         KDTRACE_HOOKS
options         DDB_CTF

# パフォーマンスオプション
options         SCHED_ULE    # ULEスケジューラ(デフォルト)
options         PREEMPTION   # プリエンプション

# メモリ制限を増加
options         MAXMEM=(16*1024)  # 16GBまで

# 特定のファイルシステム無効化
nooptions       MSDOSFS      # FAT
nooptions       CD9660       # ISO9660

設定オプションの確認

# 全オプションの説明
less /usr/src/sys/amd64/conf/NOTES
less /usr/src/sys/conf/NOTES

カーネルのビルド

ビルドコマンド

cd /usr/src

# 設定ファイルを指定してビルド
make buildkernel KERNCONF=MYKERNEL

初回は1時間くらいかかる。コーヒーでも飲んでて。

--------------------------------------------------------------
>>> Kernel build for MYKERNEL started on Mon Jan  1 12:00:00 JST 2024
--------------------------------------------------------------
>>> stage 1: configuring the kernel
config MYKERNEL
Kernel build directory is /usr/obj/usr/src/amd64.amd64/sys/MYKERNEL

>>> stage 2: building everything
make -C /usr/src/sys/MYKERNEL all
cc -c -O2 -pipe -fno-strict-aliasing ...

...(大量の出力)...

--------------------------------------------------------------
>>> Kernel build for MYKERNEL completed on Mon Jan  1 13:00:00 JST 2024
--------------------------------------------------------------

並列ビルド

# CPUコア数に合わせて並列化
make -j$(sysctl -n hw.ncpu) buildkernel KERNCONF=MYKERNEL

インストール

make installkernel KERNCONF=MYKERNEL
--------------------------------------------------------------
>>> Installing kernel MYKERNEL
--------------------------------------------------------------
install -o root -g wheel -m 555 /usr/obj/.../kernel /boot/kernel/kernel
install -o root -g wheel -m 555 /usr/obj/.../kernel.debug /usr/lib/debug/boot/kernel/kernel.debug
...

再起動

reboot

確認

uname -a
# FreeBSD hostname 14.2-RELEASE FreeBSD 14.2-RELEASE ... MYKERNEL amd64

MYKERNELが表示されてれば成功!

ワールド(ユーザーランド)のビルド

カーネルだけじゃなく、ユーザーランド全体もビルドできる。

cd /usr/src

# ワールドをビルド
make -j$(sysctl -n hw.ncpu) buildworld

# インストール
make installworld

# 設定ファイルを更新
mergemaster -Ui

# または etcupdate
etcupdate

簡単なカーネル改造

起動メッセージを変更

vi /usr/src/sys/kern/init_main.c
// 424行目あたり
static void
print_caddr_t(void *data)
{
        printf("%s", (char *)data);
}

// この下にカスタムメッセージを追加
static void
print_welcome_message(void *data)
{
        printf("\n");
        printf("===================================\n");
        printf("  Welcome to My Custom FreeBSD!   \n");
        printf("  Built by Aqua                   \n");
        printf("===================================\n");
        printf("\n");
}

SYSINIT(announce, SI_SUB_COPYRIGHT, SI_ORDER_FIRST, print_welcome_message, NULL);

再ビルド&インストール

cd /usr/src
make buildkernel KERNCONF=MYKERNEL
make installkernel KERNCONF=MYKERNEL
reboot

起動時にカスタムメッセージが表示される!

カーネルソースの読み方

重要なファイル

# プロセス管理
/usr/src/sys/kern/kern_proc.c
/usr/src/sys/kern/kern_fork.c

# システムコール
/usr/src/sys/kern/syscalls.master    # システムコール定義
/usr/src/sys/kern/kern_descrip.c     # ファイルディスクリプタ

# メモリ管理
/usr/src/sys/vm/vm_page.c
/usr/src/sys/vm/vm_fault.c

# ファイルシステム
/usr/src/sys/kern/vfs_syscalls.c
/usr/src/sys/ufs/ffs/ffs_vfsops.c

# ネットワーク
/usr/src/sys/netinet/tcp_input.c
/usr/src/sys/netinet/tcp_output.c

コードを追いかけるコツ

# grep + cscope が便利
cd /usr/src/sys

# cscopeデータベース作成
find . -name "*.[ch]" > cscope.files
cscope -b -q

# cscope起動
cscope -d
# 's' でシンボル検索
# 'g' で定義を検索
# 'c' で呼び出し元を検索

デバッグ方法

DDBカーネルデバッガ

# カーネル設定に追加(前述)
options         KDB
options         DDB
# 起動時にDDBに入る
# /boot/loader.conf に追加
debug.debugger_on_panic="1"

パニック時やCtrl+Alt+Escで対話型デバッガに入る。

Stopped at      breakpoint_here+0x4:    ret
db> trace        # スタックトレース
db> ps           # プロセス一覧
db> show pcpu    # CPU情報
db> cont         # 続行

printfデバッグ

カーネルではprintfが使える。

#include <sys/param.h>
#include <sys/systm.h>

void my_function(void) {
    printf("DEBUG: my_function called\n");
}

KASSERT(アサーション)

#include <sys/param.h>
#include <sys/systm.h>

void my_function(struct proc *p) {
    KASSERT(p != NULL, ("my_function: p is NULL"));
    // ...
}

INVARIANTSオプションを有効にしてビルドすると、KASSERTが有効になる。

まとめ

FreeBSDカーネル開発の入り口:

  1. ソースツリーがシンプルで理解しやすい
  2. GENERICをコピーしてカスタム設定を作る
  3. make buildkernelでビルド
  4. make installkernelでインストール
  5. DDBやprintfでデバッグ

Linuxカーネルより入りやすいと思う。構造がシンプルで、ドキュメントも充実してる。

次回予告

Part2: カーネルモジュールを作って動的にロードする

毎回カーネルを再ビルドするのは面倒。カーネルモジュールを作れば、動的にロード/アンロードできる。「Hello, World」モジュールから実用的なモジュールまで作ってみよう。

この記事が役に立ったら、いいね・ストックしてもらえると嬉しいです!

8
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?