💨

ARM版Mac上のDocker環境でのARM64 Linuxカーネルビルドとセットアップガイド

2024/09/20に公開

【ARM版Mac + Docker】ARM64向けLinuxカーネルのビルドとQEMUでの実行手順

こんにちは。この記事では、ARM版Mac(Apple Silicon)上のDocker環境でARM64向けのLinuxカーネルをビルドし、QEMU上で実行する手順を、Linuxのセットアップ経験が少ないエンジニアの方々向けに詳しく解説します。カーネルのビルド手順と、QEMUで実行するための手順を明確に分けて説明し、各ステップの目的や背景も含めて解説します。


目次

  1. はじめに
  2. Dockerコンテナの起動
  3. カーネルビルドに必要な手順
  4. QEMUでの実行に必要な手順
  5. ログインとシステムの確認
  6. トラブルシューティング
  7. まとめ

はじめに

ARM64アーキテクチャ向けのLinuxカーネルをビルドし、エミュレータ上で動作させることは、組み込みシステムやカーネル開発を学ぶ上で非常に有益です。ARM版Mac(Apple Silicon)ユーザーにとって、Dockerを使用することで、クリーンで再現性の高い環境でこのプロセスを行うことができます。

本記事では、Docker上でのカーネルのビルド手順とQEMUでの実行手順を分けて説明し、各ステップの目的や背景も含めて解説します。Linuxのセットアップ経験が少ない方でも理解しやすいように、専門用語の説明や各手順の意味を詳しく解説していきます。

この記事では、ARM版MacにDockerがすでにインストールされていることを前提としています。


Dockerコンテナの起動

まず、ARM版Mac上でターミナルを開き、以下のコマンドを使用してUbuntuの最新版のDockerコンテナを起動します:

docker run --privileged -it --name linux-build ubuntu:latest /bin/bash

このコマンドの詳細な説明:

  • docker run: Dockerコンテナを新しく作成し、起動するコマンドです。

  • --privileged: コンテナに特権モードを付与します。これにより、通常のコンテナでは制限されている操作(例:カーネルモジュールのロード、デバイスの操作など)が可能になります。カーネルビルドやQEMU実行に必要な低レベルの操作を行うために必要です。

  • -it: 2つのオプションの組み合わせです。-iはインタラクティブモードを有効にし、-tは疑似TTY(ターミナル)を割り当てます。これにより、コンテナ内でインタラクティブなシェルセッションを使用できます。

  • --name linux-build: コンテナに「linux-build」という名前を付けます。これにより、後でこの名前を使用してコンテナを参照できます。

  • ubuntu:latest: 使用するDockerイメージを指定します。この場合、UbuntuのLatest(最新)バージョンのイメージを使用します。ARM版Macでは、自動的にARM64アーキテクチャ用のイメージが選択されます。

  • /bin/bash: コンテナ起動時に実行するコマンドを指定します。この場合、bashシェルを起動し、対話的な操作が可能になります。

注意事項:

  1. 特権モード(--privileged)は、セキュリティ上のリスクを伴うため、本番環境での使用には適していません。学習目的の個人環境でのみ使用してください。
  2. ARM版MacでこのコマンドをCOPYして実行する場合、すべてのオプションがそのまま機能します。特別な変更は必要ありません。
  3. ubuntu:latestを使用することで、常に最新のUbuntuバージョンが利用できますが、バージョンの変更に伴う予期せぬ問題が発生する可能性もあります。安定性を重視する場合は、特定のバージョン(例:ubuntu:20.04)を指定することも検討してください。

このコマンドを実行すると、ARM64アーキテクチャ用のUbuntuコンテナが起動し、カーネルビルドやQEMUでの実行に必要な環境が整います。


カーネルビルドに必要な手順

3.1 必要なパッケージのインストール

コンテナ内で以下のコマンドを実行し、カーネルビルドに必要なパッケージをインストールします:

apt update
apt install -y build-essential libncurses-dev bison flex libssl-dev libelf-dev wget git bc python3

これらのパッケージの役割:

  • build-essential:C/C++コンパイラ(gcc/g++)、makeなどの基本的なビルドツールを含むメタパッケージです。カーネルのコンパイルに不可欠で、ソースコードのコンパイルとリンクを行います。

  • libncurses-dev:テキストベースのユーザーインターフェース用ライブラリです。カーネルの設定メニュー(make menuconfig)の表示に使用され、カーネル設定の対話的な編集を可能にします。

  • bison:構文解析ツールで、カーネルのビルドプロセス中に特定のソースファイルの解析に使用されます。特に、カーネルの設定ファイルの解析に重要な役割を果たします。

  • flex:字句解析ツールで、bisonと共に使用され、ソースコードの解析に役立ちます。カーネルのビルドプロセスで特定のファイルの前処理に使用されます。

  • libssl-dev:OpenSSLの開発ライブラリです。カーネルの暗号化機能やセキュリティ関連の機能のビルドに必要で、特に暗号化モジュールの構築に使用されます。

  • libelf-dev:ELF(Executable and Linkable Format)ファイルを扱うためのライブラリです。カーネルモジュールの処理やデバッグ情報の生成に使用され、カーネルのロードやモジュールの動的ロードに関連します。

  • wget:ウェブからファイルをダウンロードするためのツールです。カーネルソースのダウンロードに使用され、ソースコードや必要なパッチの取得を自動化します。

  • git:分散バージョン管理システムです。カーネルソースの取得や管理に使用でき、特定のバージョンやブランチのチェックアウト、パッチの適用などに役立ちます。

  • bc:任意精度の計算言語で、カーネルのビルドスクリプト内の計算に使用されます。特に、カーネルの設定やバージョン番号の生成時に必要となります。

  • python3:Pythonプログラミング言語のインタプリタです。一部のカーネルビルドスクリプトやツールがPythonで書かれているため必要です。特に、カーネルの設定やビルドプロセスの自動化に使用されます。

これらのパッケージは、Linuxカーネルのビルドプロセス全体を通じて様々な場面で使用されます。それぞれが特定の役割を持ち、カーネルのソースコードの取得、設定、コンパイル、モジュールの構築などの作業を可能にします。これらのツールを組み合わせることで、複雑なカーネルビルドプロセスを効率的に実行することができます。

3.2 Linuxカーネルのダウンロードとビルド

最新のLinuxカーネルソースコードをダウンロードし、デフォルト設定でビルドします。

cd /usr/src
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.10.10.tar.xz
tar -xf linux-6.10.10.tar.xz
cd linux-6.10.10

カーネルの設定

make defconfig

このコマンドは、ARM64アーキテクチャのデフォルト設定を使用してカーネルを設定します。

カーネルのビルド

make -j$(nproc)

このコマンドでカーネルのビルドを開始します。-j$(nproc)オプションは、利用可能なすべてのCPUコアを使用してビルドを並列化し、処理を高速化します。

ビルドが完了すると、arch/arm64/boot/ImageにARM64向けのカーネルイメージが生成されます。


QEMUでの実行に必要な手順

4.1 ルートファイルシステムの作成

ARM64向けのルートファイルシステムを debootstrap を使用して作成します。

まず、必要なパッケージをインストールします:

apt install -y qemu-system-arm qemu-efi-aarch64 qemu-user-static debootstrap

次に、ルートファイルシステムを作成します:

debootstrap --arch=arm64 focal ./ubuntu-rootfs http://ports.ubuntu.com/ubuntu-ports/

このコマンドの意味:

  • --arch=arm64:ARM64アーキテクチャ用のシステムを作成
  • focal:Ubuntu 20.04のコードネーム
  • ./ubuntu-rootfs:ルートファイルシステムを作成するディレクトリ
  • http://ports.ubuntu.com/ubuntu-ports/:ARM64用のUbuntuパッケージを取得するリポジトリ

4.2 ルートファイルシステムのイメージ化

作成したルートファイルシステムをディスクイメージにコピーします。

dd if=/dev/zero of=rootfs.img bs=1G count=2
mkfs.ext4 rootfs.img
mkdir mnt
mount rootfs.img mnt
cp -a ubuntu-rootfs/* mnt/

これらのコマンドの意味:

  1. 2GBの空のディスクイメージファイルを作成
  2. イメージファイルにext4ファイルシステムを作成
  3. イメージをマウントするためのディレクトリを作成
  4. イメージをマウント
  5. ルートファイルシステムの内容をコピー

4.3 chrootでの初期設定

ARM64バイナリを実行するために、qemu-aarch64-static をコピーし、chroot環境で初期設定を行います。

cp /usr/bin/qemu-aarch64-static mnt/usr/bin/
chroot mnt /bin/bash

chroot環境内で以下のコマンドを実行します:

passwd  # rootパスワードを設定
adduser hoge  # 'hoge'は任意のユーザー名
exit  # chroot環境を抜ける

最後に、イメージをアンマウントします:

umount mnt

4.4 QEMUでのカーネル起動

以下のコマンドでQEMUを起動し、ビルドしたカーネルとルートファイルシステムを使用してARM64環境を立ち上げます。

qemu-system-aarch64 -M virt -cpu cortex-a57 -smp 2 -m 1024 \
  -kernel arch/arm64/boot/Image \
  -append "root=/dev/vda rw console=ttyAMA0" \
  -drive if=none,file=rootfs.img,format=raw,id=hd0 \
  -device virtio-blk-device,drive=hd0 \
  -netdev user,id=net0 \
  -device virtio-net-device,netdev=net0 \
  -nographic

このコマンドの主なオプションの説明:

  • -M virt:仮想マシンタイプを指定
  • -cpu cortex-a57:エミュレートするCPUタイプを指定
  • -smp 2:2つのCPUコアを使用
  • -m 1024:1024MB(1GB)のRAMを割り当て
  • -kernel arch/arm64/boot/Image:使用するカーネルイメージを指定
  • -append "root=/dev/vda rw console=ttyAMA0":カーネルに渡す起動オプション
  • -drive if=none,file=rootfs.img,format=raw,id=hd0:ルートファイルシステムのイメージを指定
  • -device virtio-blk-device,drive=hd0:仮想ブロックデバイスを設定
  • -netdev user,id=net0:ネットワークを設定
  • -device virtio-net-device,netdev=net0:仮想ネットワークデバイスを設定
  • -nographic:グラフィカルウィンドウを使用せず、テキストモードで起動

ログインとシステムの確認

QEMUが正常に起動すると、ログインプロンプトが表示されます。

設定したrootパスワードまたは作成したユーザーでログインし、以下のコマンドでシステムを確認できます:

uname -a  # カーネルバージョンとアーキテクチャの確認
cat /etc/os-release  # OSの情報確認
free -m  # メモリ使用量の確認
df -h  # ディスク使用量の確認

トラブルシューティング

1. Dockerコンテナが起動しない場合

解決策:

  • Docker Desktopが正常に起動しているか確認してください。
  • ARM版Mac用のDockerを使用していることを確認してください。

参考リンク


ご質問やフィードバックがありましたら、お気軽にコメントしてください。この記事が、ARM版MacユーザーのDockerを使用したカーネル開発やシステムプログラミングの学習の一助となれば幸いです。

Discussion