Raspbian でffmpegをセルフビルドしてみた
Rapberry Pi 2 のRapbian jessieでffmpegをセルフビルドしてみました。
準備
$ sudo apt-get update $ sudo apt-get -y --force-yes install autoconf automake build-essential libass-dev libfreetype6-dev \ libsdl1.2-dev libtheora-dev libtool libva-dev libvdpau-dev libvorbis-dev libxcb1-dev libxcb-shm0-dev \ libxcb-xfixes0-dev pkg-config texinfo zlib1g-dev $ sudo apt-get install yasm $ sudo apt-get install libx264-dev
fdk-aacのビルド
$ mkdir $HOME/work/ffmpeg $ cd $HOME/work/ffmpeg/ $ wget -O fdk-aac.tar.gz https://github.com/mstorsjo/fdk-aac/tarball/master $ tar xvzf fdk-aac.tar.gz $ cd mstorsjo-fdk-*/ $ autoreconf -fiv $ ./configure $ make -j4 $ sudo make install
ffmpegのビルド
今回はx265は省略。
$ cd $HOME/work/ffmpeg/ $ wget https://www.ffmpeg.org/releases/ffmpeg-2.7.2.tar.xz $ tar xf ffmpeg-2.7.2.tar.xz $ cd ffmpeg-2.7.2/ $ vi myconfig.sh $ sh myconfig.sh $ time make -j4 2>&1 |tee make.log $ sudo make install
myconfig.shの内容は
./configure \ --enable-gpl \ --enable-libass \ --enable-libfdk-aac \ --enable-libfreetype \ --enable-libtheora \ --enable-libvorbis \ --enable-libx264 \ --enable-nonfree
ビルドには一時間くらいかかりました。
できたffmpegを実行すると、libfdk-acc.so がみつからないというエラーになってしまいました。これは/usr/local/libに確かにあるのになんでだろう?と少し悩みましたが、これを実行しないと反映されないことを忘れていました。
$ sudo /sbin/ldconfig
これで問題なく起動できるようになりました。
$ ffmpeg -version ffmpeg version 2.7.2 Copyright (c) 2000-2015 the FFmpeg developers built with gcc 4.9.2 (Raspbian 4.9.2-10) configuration: --enable-gpl --enable-libass --enable-libfdk-aac --enable-libfreetype --enable-libtheora --enable-libvorbis --enable-libx264 --enable-nonfree libavutil 54. 27.100 / 54. 27.100 libavcodec 56. 41.100 / 56. 41.100 libavformat 56. 36.100 / 56. 36.100 libavdevice 56. 4.100 / 56. 4.100 libavfilter 5. 16.101 / 5. 16.101 libswscale 3. 1.101 / 3. 1.101 libswresample 1. 2.100 / 1. 2.100 libpostproc 53. 3.100 / 53. 3.100
クロスコンパイルする方法はこちら。
CompilationGuide/RaspberryPi
PCMのデータを自分でいじってデジタルオーディオを理解する
私はいままで音を扱ったことはなかったので、PCMのことは聞いたことがあるという程度でした。仕事でオーディオのデバイスドライバを触ることになったので、その前提知識としてPCMのことを調べていたのですが、実際にいろいろといじってみたらとてもよく理解できたので紹介します。
PCMとは
高校の物理で習ったとおり、音は空気の振動の波です。マイクの音はアナログの波形として入力されますが、AUDIO CODECと呼ばれるチップでデジタルの波形に変換されてコンピュータに入ってきます。逆に音を出すときにはデジタルの波形をAUDIO CODECに流すと、そこでアナログの波形に変換されてスピーカーを鳴らします。
このAUDIO CODECとやりとりするデジタルの波形のフォーマットがPCMです。
PCM(Pluse Code Modulation)についてはこちらの記事がわかりやすいです。
oblÌîbm¯
ここでは主に量子化ビット数:16, サンプリングレート48kHzのPCMデータを扱います。
ffmpegでPCMデータを扱う
本題はPCMデータの加工なので、その前後の面倒なところはffmpegにやってもらいます。
音声ファイルをPCMデータに変換する
$ ffmpeg -i src.ogg -f s16le -ar 48k -ac 2 d.pcm
ar はサンプリングレート。ac はチャネル数。ステレオなら2, モノラルなら1
PCMデータを音声ファイルに変換する
$ ffmpeg -f s16le -ar 48k -ac 2 -i d.pcm d.wav
PCMデータを再生する
$ ffplay -f s16le -ar 48k -ac 2 d.pcm
あるいは、alsaのutilityコマンドを使って
$ aplay -f dat d.pcm
-f dat は -f S16_LE -c2 -r48000 の省略形。
PCMデータのサンプリングレートを変換する
$ ffmpeg -f s16le -ar 48k -ac 2 -i d.pcm -f s16le -ar 44.1k -ac 2 d_441.pcm
PCMデータの中を見てみる
まずは手元にあるPCMのデータをダンプして中をのぞいてみます。これは 16bitのモノラル、サンプリングレート48kHzのデータです。
$ od -x a.pcm |head 0000000 0003 0003 0003 0004 0003 0002 0004 0001 0000020 0004 0004 0002 0002 0002 0001 0005 0003 0000040 0002 0002 0000 0003 0002 0005 0006 0002 0000060 0005 0004 0000 0005 0003 0001 0001 0003 0000100 fff5 001b ffe0 0040 ff87 07b5 037e 0292 0000120 02be 0256 0273 022f 01c2 012a 011d 0164 0000140 0157 00e6 007c 0070 00e2 01a8 0214 01cc 0000160 0167 014d 016f 01a0 019b 0133 00a4 0027 0000200 fffc 0029 0075 0092 004b ffe7 ffc6 ffc3 0000220 ffd3 ffee ffdf ff97 ff40 fef0 fed4 fef1
このデータのファイルサイズは約3MB。
$ ls -l a.pcm -rwxr-xr-x 1 koba koba 3105280 Sep 30 10:09 a.pcm
再生してみます。
$ ffplay -f s16le -ar 48k -ac 1 a.pcm ... [s16le @ 0x7fc9440008c0] Estimating duration from bitrate, this may be inaccurate Input #0, s16le, from 'a.pcm': Duration: 00:00:32.35, bitrate: 767 kb/s Stream #0:0: Audio: pcm_s16le, 48000 Hz, 1 channels, s16, 768 kb/s 35.37 M-A: -0.000 fd= 0 aq= 0KB vq= 0KB sq= 0B f=0/0
正しく再生できました。
演奏時間は約32秒。16bitは2バイトなので
2 * 48000 * 32 = 3,072,000
ファイルサイズとのつじつまも合います。
モノラル(1ch)のPCMデータをステレオに変換する
モノラルのPCMデータは符号付き16bitのデータが単純に並んでいるだけです。そしてステレオのデータはそれが16bit x2のペアが並びます。
以下のようなCの関数で、元のデータにひとつづつ0を挿入してみます。
int mono2left(char *inbuf, char *outbuf, int len) { int16_t *inp; int16_t *outp; int cnt = len / sizeof(int16_t); inp = (int16_t*)inbuf; outp = (int16_t*)outbuf; while (cnt-- > 0) { *outp++ = *inp; *outp++ = 0; inp++; } return (char*)outp - outbuf; }
mono2left.c
そしてでき上がったデータがこちら。
$ od -x a_left.pcm |head 0000000 0003 0000 0003 0000 0003 0000 0004 0000 0000020 0003 0000 0002 0000 0004 0000 0001 0000 0000040 0004 0000 0004 0000 0002 0000 0002 0000 0000060 0002 0000 0001 0000 0005 0000 0003 0000 0000100 0002 0000 0002 0000 0000 0000 0003 0000 0000120 0002 0000 0005 0000 0006 0000 0002 0000 0000140 0005 0000 0004 0000 0000 0000 0005 0000 0000160 0003 0000 0001 0000 0001 0000 0003 0000 0000200 fff5 0000 001b 0000 ffe0 0000 0040 0000 0000220 ff87 0000 07b5 0000 037e 0000 0292 0000
これを -ac 1 を 2 に変えて再生してみます。
$ ffplay -f s16le -ar 48k -ac 2 a_left.pcm
みごとに元の音が左チャネルからでるステレオのPCMデータになりました。
以下のようにすれば、右チャネルからでるようになります。
while (cnt-- > 0) { *outp++ = 0; *outp++ = *inp; inp++; }
mono2right.c
以下のようにすれば左右両方から同じ音が出ます。
while (cnt-- > 0) { *outp++ = *inp; *outp++ = *inp; inp++; }
mono2stereo.c
なるほど。
PCMデータの音量を変更する
高校の物理で習ったとおり、音の大きさは波形の振幅で決まります。振幅を変更するにはかけ算でできます。
以下の関数は左と右で独立にボリュームを変更できるようにしてみました。
int changeVol(char *inbuf, char *outbuf, int len, float vol_l, float vol_r) { int16_t *inp; int16_t *outp; int cnt = len / sizeof(int16_t) / 2; inp = (int16_t*)inbuf; outp = (int16_t*)outbuf; while (cnt-- > 0) { *outp++ = *inp++ * vol_l; *outp++ = *inp++ * vol_r; } return (char*)outp - outbuf; }
vol.c
これで音の大きさが変わりました。
2つのPCMデータをミックスする
高校の物理で習ったとおり、2つの音の合成は足し算です。
実際には16bitで表現できる範囲を超えてしまうとまずいので、ボリュームを絞ってから足し算するようにします。
ただし2つのPCMデータを合成するには、そのフォーマット(量子化ビット数、サンプリングレート)が同じであることが前提になります。(その変換はffmpegなどのツールでやっておきます。)
int mix(char *inbuf1, char *inbuf2, char *outbuf, int len, float vol1, float vol2) { int16_t *inp1, *inp2; int16_t *outp; int cnt = len / sizeof(int16_t); inp1 = (int16_t*)inbuf1; inp2 = (int16_t*)inbuf2; outp = (int16_t*)outbuf; while (cnt-- > 0) { *outp++ = (*inp1++ * vol1) + (*inp2++ * vol2); } return (char*)outp - outbuf; }
mix.c
確かにこれで2つのPCMデータを混ぜることができました。単純なミキサーの原理がわかりました。
PCMデータの部分切り出し
PCMデータはモノラルなら2バイト、ステレオなら4バイトのデータの羅列です。なので、head, tailコマンドをバイト単位で指定することで任意の部分を切り出すことができます。
ステレオ、48kHzなら1秒間のデータ長は2 * 2 * 48000 = 192000 になります。
先頭の1秒間だけ切り出す
$ head --byte=192000 a2.pcm > a2_first1sec.pcm
最後の1秒間を捨てる
$ head --byte=-192000 a2.pcm > a2_all_but_last1sec.pcm
最後の1秒間だけ切り出す
$ tail --byte=192000 a2.pcm > a2_last1sec.pcm
先頭の1秒間を捨てる
$ tail --byte=+192000 a2.pcm > a2_all_but_first1sec.pcm
PCMデータの連結
連結は単にcatコマンドでつなぐだけです。
$ cat a2.pcm b2.pcm > c2.pcm
回数を指定してリピートするには以下のようにループを回します。
$ rm -f a2_10times.pcm $ for i in `seq 10`; do cat a2.pcm >> a2_10times.pcm; done
まとめ
PCMデータの基本的な加工はこのように簡単な演算でできることがわかりました。これらを組み合わせれば、自在にテストデータを作れそうです。
実際にデータを加工して、その音を聞いて確認することを繰り返すうちにPCMデータがどんなものなのかを体で理解することができました。
参考
Ubuntu 14.04でffmpegをビルドしてみた
基本的にこのページの内容をなぞっただけです。
CompilationGuide/Ubuntu – FFmpeg
準備
ソースとライブラリを置くディレクトリの作成と必要なライブラリの取得。
$ mkdir $HOME/work/ffmpeg $ mkdir $HOME/work/ffmpeg/build $ sudo apt-get update $ sudo apt-get -y --force-yes install autoconf automake build-essential libass-dev libfreetype6-dev \ libsdl1.2-dev libtheora-dev libtool libva-dev libvdpau-dev libvorbis-dev libxcb1-dev libxcb-shm0-dev \ libxcb-xfixes0-dev pkg-config texinfo zlib1g-dev $ sudo apt-get install yasm $ sudo apt-get install libx264-dev
libx265のビルド
$ cd $HOME/work/ffmpeg $ sudo apt-get install cmake mercurial $ hg clone https://bitbucket.org/multicoreware/x265 $ cd x265/build/linux/ $ PATH="$HOME/bin:$PATH" cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX="$HOME/work/ffmpeg/build" -DENABLE_SHARED:bool=off ../../source $ make $ make install $ make clean
libfdk-aacのビルド
$ cd $HOME/work/ffmpeg $ wget -O fdk-aac.tar.gz https://github.com/mstorsjo/fdk-aac/tarball/master $ tar xvzf fdk-aac.tar.gz $ cd mstorsjo-fdk-aac-047376a/ $ autoreconf -fiv $ ./configure --prefix="$HOME/work/ffmpeg/build" --disable-shared $ make $ make install $ make distclean
ffmpegのビルド
$ cd $HOME/work/ffmpeg $ tar xvf ~/Downloads/ffmpeg-2.7.2.tar.xz $ cd ffmpeg-2.7.2/ $ vi myconfig.sh $ sh myconfig.sh $ make $ make install
myconfig.shの内容は以下の通り。
PKG_CONFIG_PATH="$HOME/work/ffmpeg/build/lib/pkgconfig" ./configure \ --prefix="$HOME/work/ffmpeg/build" \ --pkg-config-flags="--static" \ --extra-cflags="-I$HOME/work/ffmpeg/build/include" \ --extra-ldflags="-L$HOME/work/ffmpeg/build/lib" \ --bindir="$HOME/bin" \ --enable-gpl \ --enable-libass \ --enable-libfdk-aac \ --enable-libfreetype \ --enable-libtheora \ --enable-libvorbis \ --enable-libx264 \ --enable-libx265 \ --enable-nonfree #--enable-libmp3lame \ #--enable-libopus \ #--enable-libvpx \
できた。
$ which ffmpeg /home/koba/bin/ffmpeg $ ffmpeg -version ffmpeg version 2.7.2 Copyright (c) 2000-2015 the FFmpeg developers built with gcc 4.8 (Ubuntu 4.8.4-2ubuntu1~14.04) configuration: --prefix=/home/koba/work/ffmpeg/build --pkg-config-flags=--static --extra-cflags=-I/home/koba/work/ffmpeg/build/include --extra-ldflags=-L/home/koba/work/ffmpeg/build/lib --bindir=/home/koba/bin --enable-gpl --enable-libass --enable-libfdk-aac --enable-libfreetype --enable-libtheora --enable-libvorbis --enable-libx264 --enable-libx265 --enable-nonfree libavutil 54. 27.100 / 54. 27.100 libavcodec 56. 41.100 / 56. 41.100 libavformat 56. 36.100 / 56. 36.100 libavdevice 56. 4.100 / 56. 4.100 libavfilter 5. 16.101 / 5. 16.101 libswscale 3. 1.101 / 3. 1.101 libswresample 1. 2.100 / 1. 2.100 libpostproc 53. 3.100 / 53. 3.100
Ubuntu 14.04でcdebootstrapを使う
岩松さんの発表スライドを見て、cdebootstrap というものを知りました。
Raspberry Pi 2 Model BにDebian Jessie /armhfをインストールする (PDF)
Ubuntu 14.04 でこれを使おうとしてのですが、うまくいきません。
$ sudo cdebootstrap --foreign --arch armhf jessie /tmp/root http://http.debian.net/debian/ E: Unknown suite jessie
$ sudo cdebootstrap --foreign --arch armhf stable /tmp/root http://http.debian.net/debian/ P: Retrieving Release P: Retrieving Release.gpg P: Validating Release I: Good signature from "Debian Archive Automatic Signing Key (7.0/wheezy)" P: Parsing Release E: Unknown suite jessie
どうも /usr/share/cdebootstrap/suites というファイルに記述漏れがあるようです。
以下のように修正したらうまくいくようになりました。
$ diff -u /usr/share/cdebootstrap/suites.org /usr/share/cdebootstrap/suites --- /usr/share/cdebootstrap/suites.org 2013-05-15 06:01:44.000000000 +0900 +++ /usr/share/cdebootstrap/suites 2015-09-26 16:13:39.645884787 +0900 @@ -18,6 +18,14 @@ Config: generic Keyring: debian-archive-keyring.gpg +Suite: jessie +Config: generic +Keyring: debian-archive-keyring.gpg + +Suite: stretch +Config: generic +Keyring: debian-archive-keyring.gpg + Suite: sid Config: generic Keyring: debian-archive-keyring.gpg @@ -71,14 +79,18 @@ Keyring: ubuntu-archive-keyring.gpg Suite: oldstable +Config: generic Keyring: debian-archive-keyring.gpg Suite: stable +Config: generic Keyring: debian-archive-keyring.gpg Suite: testing +Config: generic Keyring: debian-archive-keyring.gpg Suite: unstable +Config: generic Keyring: debian-archive-keyring.gpg
以下のようにエラーが解消しました。
$ sudo cdebootstrap --foreign --arch armhf jessie /tmp/root http://http.debian.net/debian/ P: Retrieving Release P: Retrieving Release.gpg P: Validating Release I: Good signature from "Debian Archive Automatic Signing Key (7.0/wheezy)" P: Parsing Release P: Validating Packages.gz P: Retrieving Packages.gz P: Validating Packages.gz P: Parsing Packages P: Retrieving gcc-4.9-base P: Validating gcc-4.9-base P: Retrieving multiarch-support P: Validating multiarch-support P: Retrieving libgcc1 ...
でもまだすっきりとはいきませんでした。
次のトラブルは次の記事で。
cdebootstrapを使ってRaspberry Pi 2にDebain jessie armhf をインストールする - 組み込みの人。
cdebootstrapを使ってRaspberry Pi 2にDebain jessie armhf をインストールする
今回もまたNFSrootを使用します。
まずはcdebootstrapでNFSでexportするディレクトリにroot file system の元を作成します。
sudo mkdir /export/armhf_jessie sudo cdebootstrap --foreign --arch armhf --include=openssh-server,ntp,ca-certificates,vim,sudo jessie /export/armhf_jessie/ http://http.debian.net/debian/
次にここからRaspberry Pi 2を起動するようにします。
Raspberry Pi 2のSDカードの/boot/cmdline.txt は以下のようにNFSサーバの/export/armhf_jessie をrootに指定します。
dwc_otg.lpm_enable=0 console=ttyAMA0,115200 root=/dev/nfs nfsroot=192.168.0.6:/export/armhf_jessie rw ip=dhcp elevator=deadline rootwait
前回のdebootstrapを使ったときと異なり、今回はinit=/bin/sh を追加する必要がありません。
/sbin/init が置き換えられていて、cdebootstrapのsecond stageが自動で実行されるようになっています。
しかし、実際に起動してみると以下のようなカーネルパニックを起こしました。
[ 5.544858] VFS: Mounted root (nfs filesystem) on device 0:15. [ 5.552191] devtmpfs: mounted [ 5.555929] Freeing unused kernel memory: 416K (80776000 - 807de000) trap: ERR: bad trap [ 5.905671] Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000100 [ 5.905671] [ 5.914815] CPU: 0 PID: 1 Comm: init Not tainted 4.1.7-v7+ #2 [ 5.920551] Hardware name: BCM2709 [ 5.923987] [<80018440>] (unwind_backtrace) from [<80013e0c>] (show_stack+0x20/0x24) [ 5.931734] [<80013e0c>] (show_stack) from [<80558548>] (dump_stack+0x98/0xe0) [ 5.938959] [<80558548>] (dump_stack) from [<8055473c>] (panic+0xa4/0x204) [ 5.945836] [<8055473c>] (panic) from [<8002937c>] (do_exit+0xa0c/0xa64) [ 5.952536] [<8002937c>] (do_exit) from [<80029470>] (do_group_exit+0x50/0xcc) [ 5.959755] [<80029470>] (do_group_exit) from [<8002950c>] (__wake_up_parent+0x0/0x30) [ 5.967670] [<8002950c>] (__wake_up_parent) from [<8000f980>] (ret_fast_syscall+0x0/0x54) [ 5.975847] CPU2: stopping [ 5.978559] CPU: 2 PID: 0 Comm: swapper/2 Not tainted 4.1.7-v7+ #2 [ 5.984727] Hardware name: BCM2709 [ 5.988141] [<80018440>] (unwind_backtrace) from [<80013e0c>] (show_stack+0x20/0x24) ...
trap: ERR がまずそうですが、調べてみるとこれはbashの拡張で、sh(dash)では使えないことがわかりました。
/sbin/cdeboostrap-foregin を修正します。
また、nfsrootのせいかrootfsをremountするところでエラーが発生するので、これを無視するようにしました。
そして、rootfile systemの構築はできるようになったのですが、rootのパスワードが未設定なのでログインできません。
なのでついでにそのシェルスクリプトの中でuserというsudo可能なユーザーを登録するようにしました。
これがそのpatchです。
cdebootstrap-foregin.patch
これで起動するとroot file systemを構築した後にuserというユーザーのパスワード入力のプロンプトが出ます。そしてオリジナルの/sbin/initが起動してログインプロンプトが出るので、先ほど登録したuserでログインできます。
そして、/etc/resolv.conf や/etc/hostname, /etc/hosts などの編集を行ってください。
cdebootstrapでの最初のブートのブートログ
debootstrapと比べるとcdebootstrapの方がinit=/bin/sh として手で編集するのを省略できるぶん楽ですね。
Raspberry Pi 2のカーネルをビルドしてみた
Raspberry Pi 2でセルフビルド
Raspbianの入ったRaspberry Pi2には最初からgitやgccが入っています。コアも4つあることだし、カーネルでもビルドしてみるかと軽い気持ちで始めてみましたが、やはり無謀でした。
そもそもカーネルのソースリポジトリをgit clone するだけで、やたらと時間がかかります。測っていませんでしたが30分以上。
そして make -j4 でビルドしましたが、2時間以上かかりました。
これではconfigをちょっと変更して再ビルドするのも大変です。おすすめしません。負荷テストとして実行する以外は。
クロスビルド
やはり組み込みLinuxはクロスビルドが基本です。
いくつかつまづいたのですが、結局は以下のページの通りやればビルドして動かすことができました。
https://www.raspberrypi.org/documentation/linux/kernel/building.md
6コア12スレッドのマシンでmake -j12 としたときのビルド時間は約3分半でした。
つまづいたポイントは以下の2つ。
- ビルド後にコピーするファイルとして、kernel7.imgと/lib/modulesの他にdtbファイルも更新が必要。
- .configファイルとしてv3.18.11の/proc/config.gzから持ってくるのでなくmake bcm2709_defconfig する。
.configファイルにv3.18.11のを使用したらEthernetとUSBが使えませんでした。
リモートログインしてビルドしたときには、以下のスクリプトでコピーするべきファイルをひとつにまとめることができます。
set -x export KERNEL_RELEASE=`cat include/config/kernel.release` export INSTALL_MOD_PATH=../$KERNEL_RELEASE mkdir -p ../$KERNEL_RELEASE/boot/overlays make modules_install scripts/mkknlimg arch/arm/boot/zImage ../$KERNEL_RELEASE/boot/kernel7.img cp arch/arm/boot/dts/*.dtb ../$KERNEL_RELEASE/boot/ cp arch/arm/boot/dts/overlays/*.dtb ../$KERNEL_RELEASE/boot/overlays/ cd .. tar cvjf $KERNEL_RELEASE.tar.bz2 $KERNEL_RELEASE/
Raspberry Piのカーネルのgitリポジトリはタグ付けが適切にされておらず、現在動いていたv3.18.11のソースがどのコミットなのか見つけることができませんでした。
私がビルドして動かしてみたのは、rpi-4.1.yブランチの以下の時点のものです。
59e76bb dwc_otg: Force host mode to fix incorrect compute module board
(今みたら4.1.8がマージされてました。)
ブートログをgistに貼りました。
Raspberry Pi 2 カーネルv4.1.7のブートログ
Raspberry PiをNFSrootで起動する
組込みLinuxの開発ではルートファイルシステムをまるごとNFSにしてしまうと便利です。Raspberry Piが起動しているかどうかに関わらずルートファイルシステムのファイルをいじることができるようになります。
NFSサーバの準備
以下のページを見てください。
NFSサーバの設定 - 組み込みの人。
RaspbianのrootパーテションをNFSのディレクトリにコピーする
RaspbianのインストールされたSDカードをNFSサーバとなるLinuxマシンに挿します。
SDカードのrootパーティションが /media/koba/root にマウントされたとすると
$ sudo mkdir /export/raspbian $ cd /export/raspbian $ sudo cp -a /media/koba/root/ root
fstabを編集
/ をmountするところをコメントアウトします。
$ cat /export/raspbian/root/etc/fstab
proc /proc proc defaults 0 0
/dev/mmcblk0p6 /boot vfat defaults 0 2
#/dev/mmcblk0p7 / ext4 defaults,noatime 0 1
# a swapfile is not a swap partition, so no using swapon|off from here on, use dphys-swapfile swap[on|off] for that
カーネルのブートパラメータの変更
RaspbianのSDカードの/boot/cmdline.txt を以下のように変更します。(NFSサーバのIPアドレスが192.168.0.6のとき)
dwc_otg.lpm_enable=0 console=ttyAMA0,115200 root=/dev/nfs nfsroot=192.168.0.6:/export/raspbian/root rw ip=dhcp elevator=deadline rootwait
起動ログがシリアルコンソールに出るように、console=tty1 も外しました。
これで起動したときのブートログをgistに貼りました。
NFSrootで起動したブートログ
(追記)NFSのオプションパラメータのチューニング
カーネルパラメータのnfsroot= のところにNFSのオプションを指定できます。
rsize=32768,wsize=32768,tcp,vers=3 を指定するとデフォルトに比べてパフォーマンスがあがります。測定していませんが、体感的にはSDカードにルートファイルシステムを置いたときと同等になります。
dwc_otg.lpm_enable=0 console=ttyAMA0,115200 root=/dev/nfs nfsroot=192.168.0.6:/export/raspbian/root,rsize=32768,wsize=32768,tcp,vers=3 rw ip=dhcp elevator=deadline rootwait