Windows+QEMUでRaspberry Piをエミュレートする
Raspberry Pi Type B 512MBを買ったのが 8 月のこと。Raspbian をインストールして無線 LAN 接続のための USB ドングル(BUFFALO 無線 LAN 子機 WLI-UC-GNM)を挿してカメラモジュールをつないで、ちょっと遊んではみたもののそのまま放置していました。もったいない。
原因を考えてみたところ、
apt-get
などでインストールして遊びたいありもののソフトウェアはとくにない- 自分で Raspberry Pi 用のプログラムを書きたい
- 統合開発環境フリークの自分にとってはパフォーマンスが低すぎて開発機にはならない(Eclipse などがまともに動かない)
- それどころか、ちょっと複雑なライブラリをビルドしようとするとそれだけで数時間以上かかってしまう
- しかも途中でエラーが起きたりして飽きる、だるい
ということのようです。
そこで、Windows 上で Raspbian をエミュレーションし、ビルドなど面倒なことはそこでやって、実機にはバイナリのみデプロイすることにしました。基本的には QEMU – Emulating Raspberry Pi the easy way (Linux or Windows!) に書いてある方法の二番煎じです。この記事に従って作業すると、次のようなことができるようになります。
- Windows 版 QEMU の上で Raspbian OS が動き、実機の Raspberry Pi で動くバイナリをコンパイルできるようになる
- 200MB 程度しか空き容量がない Raspbian のディスクイメージを拡張し、2GB 以上の容量を確保、さまざまなパッケージをインストールできるようになる
- 256MB しかメモリを割り当てられない QEMU の制限に対し、スワップ領域を用意することで対処し、わりと多めのメモリを必要とする処理が可能になる
- ExpanDrive を使うことで、QEMU 上の Raspbian OS とホストマシンである Windows 間で簡単にファイルのやり取りができるようになる
2015 年 1 月 4 日追記; あけましておめでとうございます!
そういうのもあるのか!しかし、Windows で ARM Linux 用のクロスビルド環境を簡単に作れる方法ってあるんでしょうか?とりあえず Linux の方はこちらをどうぞ。Windows + Visual Studio でそれっぽいことをしてる人も海外にはいるようですね。
QEMU のインストール
QEMU(キューエミュ)は、Fabrice Bellard が中心となって開発しているオープンソースのプロセッサエミュレータである。
QEMU for Windowsからインストーラをダウンロードして実行します。記事執筆時点での 64bit 版 Windows 用の最新バイナリはqemu-w64-setup-20141210.exeでした。
このあと、QEMU バイナリがあるディレクトリ、例えば C:\Program Files\qemu
などへパスを通します。
Raspbian ディスクイメージなどのダウンロード
Downloads | Raspberry Pi の Operating System Images から Raspbian の最新版をダウンロードして、ZIP を展開します。記事執筆時点での最新版は 2014/12/24 リリースの December 2014 で、ファイル名は 2014-12-24-wheezy-raspbian.img
でした。
あとは、Raspberry Pi のプロセッサと互換性があるカーネルイメージが必要です。作り方が Compiling an ARM1176 kernel for QEMU に書いてありますが、幸い、ページ執筆者がダウンロード可能なバイナリを用意してくれています。リンク先の 2 行目にコンパイル済みカーネルへのリンク(kernel-qemu)があります。
一つのフォルダの中に以下の二つのファイルが入っているようにしてください。
YYYY-MM-DD-wheezy-raspbian.img
(YYYY-MM-DD は 2014-12-24 など。以降、実際のファイル名に読みかえてください)kernel-qemu
QEMU の起動
二つのファイルが揃ったフォルダの中で、コマンドプロンプトか PowerShell で以下のコマンドを実行します。うまくいけば、QEMU 上で bash が起動します。
qemu-system-armw -kernel kernel-qemu -cpu arm1176 -m 256 -M versatilepb -no-reboot -serial stdio -append "root=/dev/sda2 panic=1 rootfstype=ext4 rw init=/bin/bash" -hda YYYY-MM-DD-wheezy-raspbian.img
ここで、 nano
などを使って /etc/ld.so.preload
の内容をコメントアウトします。
nano /etc/ld.so.preload
# このあとカーソルが一文字目に合っているはずなので "#" を入力します。
# "#" が挿入されたのを確認したら Ctrl+x を押します。
# ファイルを保存するか聞かれるので y とENTERキーを順に押します。
同様の手順で /etc/udev/rules.d/90-qemu.rules
を作成します。起動時に、Raspberry Pi が通常アクセスするマウントポイント(例えば /dev/root
)からカーネルが見ているマウントポイント(例えば /dev/sda2
)へシンボリックリンクを張る内容です。
KERNEL=="sda", SYMLINK+="mmcblk0"
KERNEL=="sda?", SYMLINK+="mmcblk0p%n"
KERNEL=="sda2", SYMLINK+="root"
最後にシステムをシャットダウンします。
halt
ディスク容量の拡張と Raspbian の起動
Raspbian ディスクイメージは 200MB 程度しか空き容量がなく、いろいろなパッケージをインストールするには不足です。そこで、ディスクイメージの容量を拡張します。Linux などではdd
コマンドで容量を拡張する方法が一般的のようですが、Windows ではcopy
コマンドを使って二つのディスクイメージを連結すれば同じ結果を得られます。 Is it possible to resize a QEMU disk image? を参考にしました。
# 2GB拡張する場合
qemu-img create -f raw temp.img 2G
copy /b YYYY-MM-DD-wheezy-raspbian.img+temp.img raspbian.img
以降、QEMU では生成された raspbian.img
を使います。 YYYY-MM-DD-wheezy-raspbian.img
はごみ箱に捨てて構いません。 temp.img
はあとでスワップ領域用に再利用します。
先ほどの起動コマンドから init=/bin/bash
を消し、 -hda
オプションが YYYY-MM-DD-wheezy-raspbian.img
でなく raspbian.img
を指すようにします。
qemu-system-armw -kernel kernel-qemu -cpu arm1176 -m 256 -M versatilepb -no-reboot -serial stdio -append "root=/dev/sda2 panic=1 rootfstype=ext4 rw" -hda raspbian.img
Raspbian にユーザ名 pi
パスワード raspberry
でログインしたら、fdisk
でパーティションテーブルを書き換え、Raspbian が使えるディスク容量を増やします。
sudo fdisk /dev/sda
ここまで書いて気づいたんですが、ほぼ同じことをしている日本の方がいますね。 Raspberry Pi のイメージファイルを拡張する という記事です。
現在のパーティションテーブルを確認します.
というところから読み進めてください。
なお、僕の環境では Raspbian 上で日本語がうまく表示できなかったのですが、 jfbterm
をインストールし、その上で作業するようにしたら解決しました。
sudo apt-get install jfbterm
スワップ領域の拡張
さて、ディスク容量も 2GB 増えて、いろいろインストールできるようになったのはいいのですが、実際にさまざまなコードをビルドしようと思うと、QEMU の 256MB のメモリ制限がきつくなってきます。僕の場合、OpenCV のビルド中にメモリが足りなくなって、 make
がエラー終了してしまいました。
qemu-system-armw
には RAM 容量を指定できる -m
オプションがあるのですが、256 を超えた値では Raspbian が起動しないそうです。
そこで、Raspberry Pi フォーラムの書き込みを参考に、先ほど作成した temp.img
を QEMU に二つ目のディスクとして読み込ませ、全体をスワップ領域として使えるようにします。起動コマンドは次の通りです。
qemu-system-armw -kernel kernel-qemu -cpu arm1176 -m 256 -M versatilepb -no-reboot -serial stdio -append "root=/dev/sda2 panic=1 rootfstype=ext4 rw" -hda raspbian.img -hdb temp.img
Raspbian が起動したら、次のコマンドを実行するだけです。
mkswap /dev/sdb
swapon /dev/sdb
もし RAM ディスクを作成できるようなソフトウェアを持っていたら、 temp.img
を RAM ディスク上に置いてやれば、アクセスが段違いに高速化すると思います。
Raspbian と Windows 間のファイル交換
QEMU 上の Raspbian とホストとなっている Windows の間でファイル交換する方法については、Raspbian 上で Samba を動かすとかやり方はいろいろあると思うのですが、僕は、SFTP サーバをネットワークドライブとしてマウントできるExpanDriveを使っています。
Raspbian はデフォルトで SSH サーバが起動するようになっているので、QEMU の起動コマンドに-redir "tcp:10022::22"
と書き足して、次のようにすれば、Windows から SSH ログインできるようになります。
qemu-system-armw -kernel kernel-qemu -cpu arm1176 -m 256 -M versatilepb -no-reboot -serial stdio -append
"root=/dev/sda2 panic=1 rootfstype=ext4 rw" -redir "tcp:10022::22" -hda raspbian.img -hdb temp.img
あとはExpanDriveで SFTP サーバ 127.0.0.1
のポート 10022
に接続すれば、Raspbian のホームディレクトリの中身が普通のフォルダのようにアクセスできるようになります。いつも使っている GUI ベースのテキストエディタで設定ファイルを編集することもできます。