Mac
RaspberryPi
raspbian
SDA

Raspberry Pi の SD カードの準備がスッキリと納得できるようになるかもしれない話(少しだけコンピュータ・アーキテクチャっぽい話も)

More than 1 year has passed since last update.

はじめに

某所での発表のために準備致しました内容でございますが大変僭越ながらこちらに公開させていただきました次第でございます。ご意見、ご指摘などいただければ幸いでございます
もし、本拙文がきっかけとなってどなたかが Raspberry Pi の SD カードの準備をスッキリと納得出来たと感じていただくことができたとしたら望外の喜びでございます

Raspberry Pi の SDカードを Mac で準備する手順の復習

手順まとめ

手順は以下になります
1. Raspberry Pi Foundation のサイトから Raspbian のイメージをダウンロードする
2. ダウンロードしたイメージを dd で SD カードの raw device に書く

ちょっと抽象的で分かりにくいかもしれません。特に一行目はともかく 二行目がなんのことかわからない という方もいらっしゃるのではないかと存じますが、そこを スッキリと納得できるように なることに御協力できれば、というのが本ドキュメントの目的でございます。
手順を詳細に見ていきます。

手順詳細

1.RaspberryPi Foundation のサイトにアクセスする

ヨーロピアンな色使いがオシャレなサイトですね。メニューバー(?)のデザインに違和感を持たれる方もいらっしゃるかもしれませんが、すぐに慣れると思います。

スクリーンショット 2015-01-09 15.14.43.png

2.メニューバーの左から2つ目の赤いバー「DOWNLOAD」をクリック

スクリーンショット 2015-01-10 16.49.36.png

3.ダウンロードサイト

ここで NOOBS はさらにややこしいので下スクロールして
Raspbian のイメージの Download Zip をクリックします

スクリーンショット 2015-01-09 15.17.04.png

4.Raspbian の SYSTEM IMAGE をダウンロード

スクリーンショット 2015-01-09 15.17.18.png

ところで、システムイメージってなんでしょうか。そんなにややこしいものでもなく、単に Raspberry Pi の boot に必要になるファイルシステム(実はFAT、理由はBCM2835内蔵のブートローダの仕組みをうまいこと使ったから)と、boot up された Linux が使うext4 のファイルシステムが書かれたブロックデバイス(SDとか)を dd コマンドでファイルに吸い上げたものです。だから逆に dd で SD に書くんですね。 これでスッキリした人は以下は読まなくてもOK です。

ダウンロードにはかなり時間がかかります
スクリーンショット 2015-01-09 15.22.40.png

5. Mac に SD カードを挿す

Mac にはSDカードスロットがないので別途、USB インターフェースのSD reader/writer が必要です。Amazon で売っている一番安い奴で十分だと思います

スクリーンショット 2015-01-10 17.01.05.png

6. Terminal を開き、diskutil コマンドで SDカードのデバイスIDを確認する

ここから、もしかしたら普段あまり馴染みのないコマンドがでてくるかもしれません。Mac には GUI 版のディスクユーティリティもあるのですがこちらでは上でダウンロードした イメージファイルを書けない ので、必然的にプリミティブな CUI を使はざるを得ない ことになります。

なぜ、プリミティブなツールをつかわなければいけないのかというと、ようするにあまり一般的でない、つまりMax OS の開発者が想定していないような使い方をしているから GUI ツールが用意してくれていないということになるのですが、その詳細は後述します。ただ、これだけ Raspberry Pi がスタンダードとして確固たる地位を築いてきている昨今、なんらかの GUI ツールが出てくる日も近いのかもしれません(私にはそんな能力ないので評論家みたいなみっともないことを言っておりますが...)

さて、ターミナルを開いて diskutil list コマンドを入力すると、以下のように見えると思います
この Mac にはストレージデバイスが /dev/disk0 と /dev/disk1 の2つ あることを示しています
GUID_partition_scheme とか FDisk_partition_scheme とかはいまは気にしないことにしましょう。これは Raspberry Pi とは関係なく、単に Mac の世界の用語です

スクリーンショット 2015-01-09 16.41.18 のコピー.png

ここで、 どちらが SD カードなのか をしっかりと見極める必要があります。コマンドの出力としてこっちのストレージは内蔵ディスクですよ、こっちは SD カードですよ、とか出してくれるとわかりやすいのですが、そういうことはしてくれません。
しかも、ここで 間違えると Mac のハードディスクを壊してしまう という恐ろしいことになるそうです(私は幸いやったことがないので ^^; 、でもまあ、dd で Mac のディスクになにか書いてしまったらそりゃこわれますよね)。恐怖です

なので、まず、外付けディスクを何も挿していない状態で diskutil list を実行して、どれが Mac の内蔵ディスクなのかを自分でよく理解しておきます。例えば私の Mac の場合、外部ストレージを全部はずして diskutil list を見ると以下のようになります

スクリーンショット 2015-01-10 21.46.32.png

パーティションの TYPE、名前、SIZE を見ておきましょう
Mac の内蔵ストレージがわかると、 それではない方 が外付けの SDカード、つまり上の例の場合は /dev/disk1 が SD カードです

ここで、外部ストレージをたくさん挿して diskutil list をすると、次の例のように挿したストレージの数だけ disk デバイスが見えてややこしくなるので、 SD 以外の外部デバイスは挿していない状態で diskutil list をすることをおすすめします。

スクリーンショット 2015-01-10 21.32.38.png

まあ、見てると何となく(特に SIZE が大きなヒント)どれが SD かは見当がつくのですが、繰り返しますが 間違えて dd すると悲劇 ですのでご注意を

7. Terminal で、dd コマンドを使って SD カードのデバイスのファイル名の頭に r をつけたファイルに書く

いま、SD カードのデバイスが /dev/disk1 だったとします。この時、ls /dev/disk* と /dev/rdisk* を見てみると下のように、それぞれ diskxxx に対応する rdiskxxx があることがわかります

スクリーンショット 2015-01-09 16.41.18.png

そこで、dd コマンドを使ってこの rdiskxxx の方にダウンロードしたイメージを書きます
dd コマンドの説明はいろいろなところにあるとおもいますが、例えばこちらなども参考になるかと思います
dd コマンドの構文は以下です

dd if=入力ファイル(とかデバイス) of=出力デバイス(とかファイル) bs=ブロックサイズ

ほかにも変換オプションとか指定できるのですが今は使いません。今の例の場合、if がダウンロードしたイメージファイル、 of が SD カードのデバイスのファイル名の頭に r をつけたファイル つまり /dev/rdisk1 になります
dd を実行するまえに、dd の対象になるファイルが automount されているとエラーになるので diskutil umountDisk で umountしておきます。実際の手順は合わせて以下になります

スクリーンショット 2015-01-09 16.45.49.png

おそらく10分〜15分ぐらいかかると思います。ここでは 669秒、約11分かかっています。ちなみに、途中経過は Cntl + Tで随時表示させることができます

スクリーンショット 2015-01-09 16.57.09.png

これで無事、RaspberryPi の起動 SDカードができあがりました。なんか あまり見かけないコマンドや意味のわからない手順が多い と感じられた方もいらっしゃったのではないでしょうか

疑問編

さて、相当わけの分からない事をやってるなとフラストレーションを溜められた方もいらっしゃるのではないでしょうか。しかも間違えると Mac が壊れる というストレスまでかかってくるという恐ろしさ。なんで、こんなフラストレーションとストレスが同時にかかる大変な作業になってしまっているのでしょうか。もしかして、初心者を怖がらせてインストール済SDカードを買わせる作戦でしょうか?

「物事には原因がある」と、ブッダも言っていたそうですが、原因が理解できると案外この苦しみも自然と解消して輪廻転生の苦しみから解脱できるのかもしれません

なぜ rdisk1 なのか

実は of=/dev/disk1 と rが付かないデバイス を指定しても最終的には同じように出来上がります。ただ、 物凄く時間がかかる 結果になります。それだったら速く終わる r のついたデバイスのほうがいいですね。
私がやってみると3倍ほど遅いようでしたが、こちらでは20倍遅いと質問されてますが、このとおり、Mac OS のような BSD を起源に持つ OS では、ブロック型デバイスに対応する raw デバイスが r 付きのファイル名で用意されている ので、そちらに書いた方が速いということです。もちろん、書き込みサイズはブロックサイズの整数倍になっていることが前提です。
ブロック型のデバイスの場合、本来、読み書きの単位はブロック単位です。SD カードの場合も SD カードの入出力コマンドは SD Association の仕様「SD Specification Part 1: Phisical Layer Specification」で規定されていて、SD カードのブロックサイズ(最大512 バイト、設定で小さくはできる)単位で書き込み開始位置を指定し、この単位でデータを書き込む必要があります。このバウンダリに合っていないデータの書き込みに対してはシステム側でバッファリングを行う必要があり、このバッファリングのメモリ転送のため通常のデバイスへの書き込みは一般に raw デバイスへの書き込みよりも遅くなります

結論:r が付かないデバイスに書いてもいいけど時間の節約のため

なぜ 1m なのか

例えば 1k とかにすると転送が何度もおきて 1m と較べて物凄く遅く(30分かかって 1/6 しか進んでないぐらい)なりました。では 2m にすると 1m に較べて速くなるかというと別に速くなりませんでした。試してみると 10m でも書き込み時間は 1m と一緒で11分でした

結論:1m あたりだとスピードはみな同じだからなんでもいいのでとりあえず 1m

なぜ dd なのか

これが最大のストレスとフラストレーションの原因なのではないでしょうか。再三繰り返したように間違うと Mac が壊れるようなコマンドをつかわなければいけないのはなぜか?普通はそんな危険なコマンドは推奨しないのではないか? なぜ、ファイルのコピーではだめなんだ?
もう一度、こちらを見てください
この /dev/disk1 ですが、実はすでに Raspberry Pi のイメージが書いてあるSD カードで diskutil list を実行した結果です

スクリーンショット 2015-01-09 16.41.18.png

この通り、Raspberry Pi のイメージを書いた SD カードは Fatファイルシステムの disk1s1 と、Linux ファイルシステムの disk1s2 の 異なったファイルシステムでフォーマットされた2つのパーティション から構成されています。dd ではなくファイルのコピーでということになると、例えば以下の手順になります

  1. 買ってきた SD カードを、物凄く小さいパーティションとその残りの2つに分ける
  2. 小さい方を Fat32 でフォーマとして、マウントして必要なファイルをコピー
  3. 大きい方を ext4 でフォーマットして、マウントして必要なファイルをコピー

パーティションを分けるとか、ext4 でフォーマットしてマウントとか、dd よりもっとややこしいことになります。しかも間違えて Mac の内蔵ディスクのパーティションをいじってしまうと惨事になる事情は dd でデバイスを間違えた時と全くいっしょです
それにしても、なんでこんなややこしい構造になっているのでしょうか?パーティションなんて ext4 のパーティションが1個あれば十分なんじゃないのか?この Fat の boot パーティションってなんなんでしょうか?その解答が、先ほども参照したこちらで紹介されているのでもう一度みてみます

RaspberryPi があれだけ安く小さく(つまり部品点数が少ない)、あれだけグラフィックが強力な(FULL Hivision の H.264 のエンコード/デコードがリアルタイムで可能)秘密は、スマートフォンのグラフィックアクセラレータに使われる BRODECOM BCM2835 をうまく使った事が大きいと思います。関係無いですが RaspberryPi では内蔵カメラや内蔵ディスプレイのインターフェースが M-PHY だったりと、ものすごくスマートフォンのアプリケーション CPU を思わせる(全くの余談ですが、変な会社というか、電話機を起源にするような設計だとベースバンド側にペリフェラルコントローラを持ってきてしまうような設計をするところもあったみたいですけど、コンピュータとモデムの役割分担みたいな感じでA側にペリフェラルコントローラもあるほうが自然だと私なんかは感じます)

脱線してすみませんでした。こちらに戻って、つまりBCM2835をCPUとして使うという面白いアイデアでコンピュータ・システムを作った場合、最初のブートローダーは BCM2835 の reset 処理から起動させるのが自然なのですが、この時 BCM2835 の内蔵のブートローダーには SD カードから FAT32 を探してきてマウントする機能があった というところが味噌になっています。ややこしくなるので本質的なところだけ書くとつまり、FAT の領域を用意しておき、その中に ext4 をブートするようなブートローダーを入れておけばあとは BCM2835 がブートしてくれる という工夫だったわけです

結論1:SD をパーティションにわけて種類の違うファイルシステムでフォーマットして... と大変なことになるので dd の方が簡単

結論2:dd も間違えると危険だけどパーティションわけるのも同じくらい危険

結論3:BCM2835 の reset シーケンスを旨いこと使った結果

因みに「なんで dd なんて変な名前なんだ?どういう意味?」という疑問にはこちらの英語版の wikipedia が詳しいです。(人によっては)昔懐かしい JCL の DD ステートメントだったんですね。私も数十年前、大学一年生の最初の計算機実習で JCL を全く書いていない FORTRAN の JOB を SUBMIT して、訳の分からないエラーメッセージの山に半泣きになった思い出が...

それはそうとしてそれでもなぜ dd なのか?なにか他にないのか

Raspberry Pi のアーキテクチャ・デザインは本当に創意工夫に満ちている感じて面白いのですが、内部にストレージを持たないで SD カードをストレージにしてしまおう、というのも当時はとても斬新でした。先ほども少し書いたのですが、SD カードの規格については SD Association が策定しているのですが、まず Part 1 で入出力を含めた物理インターフェースを定め、 Part 2 でファイルシステムを FAT16, FAT32, exFAT に定め、その前提で SD Video、SD Audio、SD Bind といったアプリケーション仕様を ファイルとフォルダ構造から 規定します。つまり、 SDカードは仕様として FAT が前提 になっていて、本来 Linux の ext系のファイルシステムは考慮されていません。 SD カードを ext でフォーマットする事自体が規格が元々考えていたことではない んですね。なので、それに使えるようなツールが何もなく、もっともプリミティブな dd 以外にありえないことになります。もっとも、SDA の規格はそもそも会社や機種を越えてのインターオペラビリティの実現のため、具体的にいうと A社の携帯で撮影した動画を書いたSDカードをB社のデジカメに挿しても認識して再生できる、そういうインターオペラビリティを実現するために Part2 以降があるものと理解しておりますが、Raspberry Pi のシステムストレージとして利用する、という目的であれば別にインターオペラビリティを考慮する必要などそもそもないので、Part 1 の物理インターフェースさえ使えれば後はどうでもいいわけですね。

結論:SD カードを ext でフォーマットしてしまうという事が規格外の柔軟な発送なので、それに対応できるツールはデバイスレベルで入出力できる dd しかない

感想

理屈がわからないでとにかく「手順」としてやっているとフラストレーションもストレスも溜るし、結果としてミスの原因にもなるようですがこの作業でミスが生じると大惨事につながりかねません
でも、わかってしまうとストレスもフラストレーションもなくなってしまったのではないでしょうか
この内容がなにか自然な、当たり前の、しょうもない事に感じていただけるようになられましたら望外の喜びでございます