sstea備忘録

日々のPCライフのメモ、備忘録、及びそれに類推する何か。
記載内容に間違い等を発見された場合はコッソリ教えてください... → sstea<a>aol.jp (<a> を @ に変えてください)


Raspberry Pi で音を出してみる

手元に USBスピーカー(iBUFFALO BSSP25U)があったので、それを接続し Raspberry Pi から音を出してみたいと思います。

◆Raspberry Pi にUSBスピーカーを接続
まずUSBスピーカーを接続し、認識しているか確認します。
$ cat /proc/asound/cards
 0 [ALSA           ]: bcm2835 - bcm2835 ALSA
                      bcm2835 ALSA
 1 [MicroII        ]: USB-Audio - Audio Advantage MicroII
                      C-Media INC. Audio Advantage MicroII at usb-bcm2708_usb-1.3, full speed

ちゃんと認識しています。
が、USB-Audio が二つ目になっているので、このままではUSBスピーカーからは音は出ません。

/etc/modprobe.d/alsa-base.conf の snd-usb-audio の行をコメントアウトします。
#options snd-usb-audio index=-2

いったん、モジュールをアンロードし、再ロードします。
$ sudo alsa unload
$ sudo modprobe snd_usb_audio
$ sudo modprobe snd_bcm2835

USB-Audio が一つ目になっているのを確認します。
$ cat /proc/asound/cards
 0 [MicroII        ]: USB-Audio - Audio Advantage MicroII
                      C-Media INC. Audio Advantage MicroII at usb-bcm2708_usb-1.3, full speed
 1 [ALSA           ]: bcm2835 - bcm2835 ALSA
                      bcm2835 ALSA

◆Raspberry Pi にしゃべってもらう

まずは、AquesTalk Pi (http://www.a-quest.com/products/aquestalkpi.html) から aquestalkpi-20130827.tar.gz をダウンロードしてきます。

それを raspberry pi 上で展開します。
$ mkdir /home/pi/local/
$ cd /home/pi/local/
$ tar xvzf aquestalkpi-20130827.tar.gz
下記を実行。
$ aquestalkpi/AquesTalkPi hello | aplay
しゃべったー!!

$ mkdir /home/pi/local/bin/
$ cd /home/pi/local/bin/
talk.sh という名前のシェルスクリプトを書いてみました。
#!/bin/sh

TALK=/home/pi/local/aquestalkpi/AquesTalkPi

${TALK} -s 120 "$*" | aplay 2> /dev/null

上記をコピペするなり、curl コマンドで取るなりします。
$ curl -O http://sstea.blog.jp/raspi/script/talk.sh
実行権限を付与します。
$ chmod 755 talk.sh
引数で渡した言葉をしゃべってくれるという簡単なシェルスクリプトです。ちゃんと動いてます。
$ ./talk.sh hello

今度は、時間をお知らせしてくれるシェルスクリプトを書いてみます。

jihou.sh
#!/bin/sh

time=`date "+%-H時、%-M分、%-S秒になりました"`

/home/pi/local/bin/talk.sh ${time}

上記をコピペするなり、curl コマンドで取るなりします。
$ curl -O http://sstea.blog.jp/raspi/script/jihou.sh
実行権限を付与します。
$ chmod 755 jihou.sh
今の時間を知らせてくれます。
$ ./jihou.sh

これで、毎時間の5分前にお知らせ、というような事も cron に登録すれば出来るようになりました。
$ crontab -e
とし、末尾に下記を追加して終了します。
  55 * * * * /home/pi/local/bin/jihou.sh

◆Raspberry Pi で音楽を鳴らす
Music Player Daemon (MPD) をインストールします。
$ sudo apt-get install mpd mpc

以前に作成した /etc/init.d/init-ramdisk に追記しておきます。
#!/bin/sh
### BEGIN INIT INFO
# Provides:       init-ramdisk
# Required-Start: $local_fs
# Required-Stop:  $local_fs
# Default-Start:  2 3 4 5
# Default-Stop:   0 1 6
### END INIT INFO

chmod 775 /var/log
mkdir -p /var/log/ConsoleKit/
mkdir -p /var/log/fsck/
mkdir -p /var/log/apt/
mkdir -p /var/log/ntpstats/
mkdir -p /var/log/samba/
mkdir -p /var/log/mpd/
chown root.ntp /var/log/ntpstats/
chown root.adm /var/log/samba/
touch /var/log/lastlog
touch /var/log/wtmp
touch /var/log/btmp
touch /var/log/mpd/mpd.log
chown root.utmp /var/log/lastlog
chown root.utmp /var/log/wtmp
chown root.utmp /var/log/btmp

music ディレクトリに適当な音楽ファイルを放り込む。
(デフォルトだと /var/lib/mpd/music/)

曲登録。
$ mpc update
$ mpc ls | mpc add
再生。おぉー、音楽、鳴りました。
$ mpc play
次の曲。
$ mpc next
設定とかもいろいろあります。詳細は "mpc help" で。
$ mpc volume 80
$ mpc repeat on

ここで一つ問題が。
mpd で音楽再生中に AquesTalk Pi でおしゃべりさせようとしても、しゃべってくれません。。。

/etc/mpd.conf の下記をコメントアウトすると音楽再生中でもおしゃべりしてくれました。声、少し小さい気がしますが。
audio_output {
    type        "alsa"
    name        "My ALSA Device"
#    device        "hw:0,0"    # optional
    format        "44100:16:2"    # optional
    mixer_device    "default"    # optional
    mixer_control    "PCM"        # optional
    mixer_index    "0"        # optional
}
ついでに下記をコメントアウトすることで、ベロベロ出てたエラーもなくなりました。
#bind_to_address   "localhost"


    次回は、ジョイスティックを繋いで操作出来るようにしてみたいと思います。


◆おまけ1
MPD にはスマホからでもアクセスできます。
世の中では MPD クライアントソフトがたくさん作られていて、スマホ用のアプリも例外なくあります。

自分もいくつか試してみて、Droid MPD Client が自分には合ってそうだったので、Xperia Z3 に入れています。

◆おまけ2
USBスピーカーを接続したまま電源入れると、起動時にプツプツ言って、立ち上がらない時がありました。

何でか結構悩みましたが、電力足りてないのか
/boot/config.txt の末尾に下記を追加したら安定しました。
safe_mode_gpio=4
max_usb_current=1


Raspberry Pi のディスクイメージを一から作る

前回カーネルも差し替えたので、以前の記事を見ながらディスクイメージのバックアップを取ろうかと思ったのですが、以前に構築した Linux Mint の仮想環境で、VirtualBox が(なぜか)ホスト側に挿した microSD カードリーダをうまく認識してくれませんでした。
仕方がないので、ディスクイメージをコネコネして、パーティションのリサイズやら何やらを行なったディスクイメージを作成することにしました。
gparted でリサイズしようと思ったんですが、アレ?イメージファイルだと、何故かリサイズ出来ないですね。。。

ちなみに、前回カーネルを差し替えたものに加えて、
NTP設定不要デーモンの停止、RAMディスクの使用、SWAPの停止、を行なっています。
SD使用量の節約のため日本語化等は見送りました。
ディスク使用量は半分弱といったところです。
$ df
Filesystem     1K-blocks    Used Available Use% Mounted on
/dev/root        3671884 1623100   1849424  47% /
devtmpfs          219996       0    219996   0% /dev
tmpfs              44836     336     44500   1% /run
tmpfs               5120       0      5120   0% /run/lock
tmpfs              89660       0     89660   0% /run/shm
/dev/mmcblk0p1     57288   10200     47088  18% /boot
tmpfs              32768       0     32768   0% /tmp
tmpfs              32768     112     32656   1% /var/log

◆ディスクイメージのベースの作成
"Win32 Disk Imager" を使用して、microSD のディスクイメージを Read し、仮想環境からも見える共有フォルダに入れておきます。以下、仮想環境の Linux Mint での操作になります。
(以下、ディスクイメージを rpi.img というファイル名で取得したとして記載しています。)
$ fdisk -l /media/sf_shared/rpi.img
ディスク /media/sf_shared/rpi.img: 3951 MB, 3951034368 バイト
ヘッド 255, セクタ 63, シリンダ 480, 合計 7716864 セクタ
Units = セクタ数 of 1 * 512 = 512 バイト
セクタサイズ (論理 / 物理): 512 バイト / 512 バイト
I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト
ディスク識別子: 0x0009bf4f

                デバイス ブート    始点      終点  ブロック   Id  システム
/media/sf_shared/rpi.img1          8192    122879    57344    c  W95 FAT32 (LBA)
/media/sf_shared/rpi.img2        122880   7716863  3796992   83  Linux

まずは、作成するディスクイメージのサイズを決めます。
今回は4GBのmicroSDをしようしているので、半分の2GBにしてみようと思います。

まず、空のファイルをイレモノとして作ります。
元のサイズの半分にした値
  (7716863 + 1) / 2 = 3858432
をcountに指定します。
$ export IMGFILE=/media/sf_shared/new.img

$ dd if=/dev/zero of=${IMGFILE} count=3858432 bs=512
これで、単にゼロ埋めされた2GBのファイルが出来上がりました。
# ちなみに、fdisk の表示される値と単位を合わせる意味で bs=512 としていますが、
# bs を(8倍の) 4096 とかにした方が、ファイルの作成時間は短くなります。
# その場合、count は(8分の1の)482304 とする必要があります。
# 詳細は↓おまけ1参照

パーティションテーブルを作成し、パーティションを2つ作成します。
fdisk コマンドで対話モードで設定しても全然問題ないんですが、表現が難しいので下記のようなコマンドにしておきます。(凄く見にくいですが、$'\n' が改行と思ってください。)
$ echo o$'\n'w | fdisk ${IMGFILE}
$ echo n$'\n'p$'\n'$'\n'8192$'\n'122879$'\n'w | fdisk ${IMGFILE}
$ echo n$'\n'p$'\n'$'\n'122880$'\n'3858431$'\n'w | fdisk ${IMGFILE}
$ echo t$'\n'1$'\n'c$'\n'w | fdisk ${IMGFILE}

これでガワだけは出来ました。
$ fdisk -l ${IMGFILE}

ディスク /media/sf_shared/new.img: 1975 MB, 1975517184 バイト
ヘッド 255, セクタ 63, シリンダ 240, 合計 3858432 セクタ
Units = セクタ数 of 1 * 512 = 512 バイト
セクタサイズ (論理 / 物理): 512 バイト / 512 バイト
I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト
ディスク識別子: 0x0177f305

                デバイス ブート    始点      終点  ブロック   Id  システム
/media/sf_shared/new.img1          8192    122879    57344    c  W95 FAT32 (LBA)
/media/sf_shared/new.img2        122880   3858431  1867776   83  Linux

# 最初はこのディスクイメージを "sudo kpartx -v -a ${IMGFILE}" して、
# "mkfs.ext4 /dev/mapper/loop0p2" とかして直接フォーマットしようとしたんですが、
# 何かうまく出来なくてmountも出来ないので、下記のような手順を踏む事にしました。

◆各パーティションイメージの作成
それぞれ
  (122879 + 1) - 8192 = 114688
  (3858431 + 1) - 122880 = 3735552
の値を指定し、各パーティションのイメージファイルを作成します。
$ dd if=/dev/zero of=boot.img count=114688 bs=512
$ dd if=/dev/zero of=rootfs.img count=3735552 bs=512
それぞれフォーマットします。
$ mkfs.vfat boot.img
$ mkfs.ext4 -F rootfs.img

元のイメージディスクをマウントします。
$ mkdir old1/ old2/ new1/ new2/
$ sudo kpartx -v -a /media/sf_shared/rpi.img
$ sudo mount /dev/mapper/loop0p1 old1/
$ sudo mount /dev/mapper/loop0p2 old2/
元のイメージディスクの中身をそれぞれ全コピーします。
$ sudo mount boot.img new1/
$ sudo mount rootfs.img new2/
$ sudo cp -a old1/* new1/
$ sudo cp -a old2/* new2/
その他変更等(.bash_history や /var/cache/* の削除等)、やりたければやって、気が済めばアンマウントします。
$ sudo umount new1/
$ sudo umount new2/
元のイメージディスクをアンマウントします。
$ sudo umount old1/
$ sudo umount old2/
$ sudo kpartx -d /media/sf_shared/rpi.img
$ rmdir old1/ old2/ new1/ new2/

◆ディスクイメージとして結合
ベースのディスクイメージの各パーティションを置き換えて出来上がりです。
$ dd if=boot.img of=${IMGFILE} seek=8192 bs=512
$ cat rootfs.img >> ${IMGFILE}
これを "Win32 Disk Imager" で microSD に書き込めば、いつでもこの環境に復帰できます。
ちなみに、このディスクイメージは圧縮したら 400MB 弱になりました。

◆おまけ1

dd コマンドでは "bs=512, count=2048" でも、"bs=1024, count =1024" でも、どちらでも 1MB (bs * count) の読み書きを行なう、という事には変わりありません。では動きとしてはどう違うのでしょうか?

dd コマンドでは、if で指定したファイルから bs 単位で read し、of で指定したファイルに bs 単位で write を行う、という操作を count 回数分繰り返します。
つまり bs 単位の read, write システムコールを count 回発行しているのです。

以下のように、strace で観察するとよく分かります。
$ strace dd if=/dev/zero of=dummy count=100 bs=512
execve("/bin/dd", ["dd", "if=/dev/zero", "of=dummy", "count=100", "bs=512"], [/* 48 vars */]) = 0
brk(0)                                  = 0x9cf4000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
            :
open("/dev/zero", O_RDONLY|O_LARGEFILE) = 3
dup2(3, 0)                              = 0
close(3)                                = 0
_llseek(0, 0, [0], SEEK_CUR)            = 0
open("dummy", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE, 0666) = 3
dup2(3, 1)                              = 1
close(3)                                = 0
clock_gettime(CLOCK_MONOTONIC, {238, 286988438}) = 0
read(0, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 512) = 512
write(1, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 512) = 512
read(0, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 512) = 512
write(1, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 512) = 512
read(0, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 512) = 512
write(1, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 512) = 512

            :

Raspbian(2015-02)のLinuxカーネルを差し替える

前記事で新バージョン(2015-02-16-raspbian-wheezy)の Raspbian をインストールしたので、Linuxカーネルも差し替えたいと思います。
以下、以前に書いた、この辺を見ながらクロスビルドしました。

微妙に手順変わってます。。。

◆カーネル/ローダブルモジュールのビルド

カーネルのクロスビルドには以前作った環境を使います。
以下、ホスト環境での操作になります。

git からLinuxカーネルのソースを取得します。
$ cd /home/mint/raspi/
$ git clone https://github.com/raspberrypi/linux.git
$ cd linux/
$ git checkout -b rpi-3.19.y remotes/origin/rpi-3.19.y
現時点の最新カーネルバージョンは 3.19.1 でした。(もうすぐ 4.0 になりますね。)

Raspberry Pi 実機上から取得したカーネルコンフィグをベースに、デバッグ関連、プロファイル関連のコンフィグを無効化したカーネルコンフィグ(これ)を使用します。(機能的にはデフォルトを維持してます。圧縮形式は lz4 に変更してますが。)

$ export ARCH=arm
$ export CROSS_COMPILE=arm-linux-gnueabihf-
$ cd /home/mint/raspi/linux/

上記のカスタマイズしたコンフィグを.config として linux ディレクトリ直下に置きます。
$ curl http://sstea.blog.jp/raspi/kbuild/kconfig-rpi-3.19.1 > .config
デフォルトのコンフィグを使用する場合は↓のようにしてもいいです。
$ make bcmrpi_defconfig

カーネルをビルドします。(コア数に応じて -j2 とかお好みで付けてあげてください)
$ make dtbs zImage modules
$ make modules_install INSTALL_MOD_PATH=../out/  INSTALL_MOD_STRIP=--strip-unneeded

前までは zImage を kernel.img にリネームするだけで問題ありませんでしたが、
dtb 使うようになってから、もう一工程、下記作業が必要になったようです。
(ここめっちゃ悩みました。詳細は↓おまけ1参照。
  mkknlimg は "git clone https://github.com/raspberrypi/tools.git" で取ってきた中にあります。)
$ cd /home/mint/raspi/
$ tools/mkimage/mkknlimg --dtok linux/arch/arm/boot/zImage out/kernel.img
dtb ファイル(bcm2708-rpi-b-plus.dtb)もコピーしておきます。
$ cp -p linux/arch/arm/boot/dts/bcm2708-rpi-b-plus.dtb out/

dtbファイルとkernel.img とローダブルモジュール郡を圧縮し、Raspberry Pi に持っていきます。
(まあ、このあたりは好きな方法で持っていってもらえればいいんですが。)
$ tar cvjf new.tar.bz2 out/

$ scp -p new.tar.bz2 pi@192.168.0.100:~
# IPアドレス部分は Raspberry Pi のIPアドレスを指定

◆クロスビルドしたLinuxカーネルへの差し替え
以下、Raspberry Pi 側での操作になります。

dtbファイルとカーネルイメージを差し替えます。
$ tar xvjf new.tar.bz2

$ sudo cp out/bcm2708-rpi-b-plus.dtb /boot/
$ sudo cp out/kernel.img /boot/
新しいカーネルバージョンのローダブルモジュールを展開します。
$ sudo cp -a out/lib/firmware/* /lib/firmware/
$ sudo cp -a out/lib/modules/3.19.1+/ /lib/modules/
リブートし、新しいカーネルの起動確認を行ないます。
$ reboot

もはや不要になったファイルは削除しておこうと思います。(必須ではないです)
$ sudo rm -rf /lib/modules/3.18.9+/ /lib/modules/3.18.9-v7+/
$ sudo rm -rf /boot.bak/

使用しない dtb ファイルや カーネルイメージファイルも削除していいですよね?
(自分が使用しているのは Raspberry Pi Model B+ モデルですので、下記ファイルは使用していません。)
$ sudo rm /boot/bcm2708-rpi-b.dtb /boot/bcm2709-rpi-2-b.dtb /boot/kernel7.img
$ df
Filesystem     1K-blocks    Used Available Use% Mounted on
/dev/root        3671884 1723412   1749112  50% /
devtmpfs          219996       0    219996   0% /dev
tmpfs              44836     452     44384   2% /run
tmpfs               5120       0      5120   0% /run/lock
tmpfs              89660       0     89660   0% /run/shm
/dev/mmcblk0p1     57288   10200     47088  18% /boot

◆おまけ1

以前のように、クロスビルドしたlinuxカーネルの zImage ファイルを kernel.img とリネームだけして、Raspberry Pi のカーネルを差し替えてみたんですが、どうも dtb ファイルを認識していないように思います。
ブートログにちらほらエラーも見えますし。
/boot/bcm2708-rpi-b-plus.dtb ファイルは確かに存在するのですが。
(ブートログは /var/log/messages で確認できます。)
[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Initializing cgroup subsys cpu
[    0.000000] Initializing cgroup subsys cpuacct
[    0.000000] Linux version 3.19.1+ (mint@Mint) (gcc version 4.8.3 20140106 (prerelease) (crosstool-NG linaro-1.13.1-4.8-2014.01 - Linaro GCC 2013.11) ) #1 PREEMPT Sat Mar 14 22:50:58 JST 2015
[    0.000000] CPU: ARMv6-compatible processor [410fb767] revision 7 (ARMv7), cr=00c5387d
[    0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT nonaliasing instruction cache
[    0.000000] Machine: BCM2708
[    0.000000] cma: Reserved 8 MiB at 0x1b800000
[    0.000000] Memory policy: Data cache writeback
            :

試しに、/boot/config.txt の末尾に
device_tree=bcm2708-rpi-b-plus.dtb
と追加し、リブートしてみたところ、
[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Initializing cgroup subsys cpu
[    0.000000] Initializing cgroup subsys cpuacct
[    0.000000] Linux version 3.19.1+ (mint@Mint) (gcc version 4.8.3 20140106 (prerelease) (crosstool-NG linaro-1.13.1-4.8-2014.01 - Linaro GCC 2013.11) ) #1 PREEMPT Sat Mar 14 22:50:58 JST 2015
[    0.000000] CPU: ARMv6-compatible processor [410fb767] revision 7 (ARMv7), cr=00c5387d
[    0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT nonaliasing instruction cache
[    0.000000] Machine model: Raspberry Pi Model B Plus
[    0.000000] cma: Reserved 8 MiB at 0x1b800000
[    0.000000] Memory policy: Data cache writeback
            :
dtb ファイル認識してますね。。。

どうして、デフォルトのカーネルイメージは config.txt に何も記載がなくても、ちゃんと正しい dtb ファイルを認識できてるんでしょうか?
カーネルバージョンの差か、コンフィグ変えたからか、とか考えていろいろ試してみたんですが、どうも関係なさそうです。
カーネルイメージに何か情報を付与してんじゃねーの?と思って、オリジナルのkernel.imgをバイナリエディタで開いてみると、、、
末尾に何か付いてますね。。。文字列が読めます。
圧縮イメージなのに読める文字列があるって事は、圧縮後に付与されたって事です。

zImageファイルはImageファイルを圧縮して自己展開プログラムを先頭にくっつけたファイルで、自分が知る限り末尾にこんな情報はくっつかないので、外部ツールなりでzImageにこの情報を付与する加工を加えているように思います。

カーネルイメージ生成手順、何か増えてんのか?と思って https://github.com/raspberrypi/tools の中をいろいろ見てると mkknlimg とかいうそれらしいのがありました。

で、コレ使って kernel.img 作ってみると、、、

$ mkknlimg --dtok zImage kernel.img
config.txt を弄らなくても、いけましたー。

◆おまけ2
CONFIG_KALLSYMS を無効化しようとして毎回、迷子になるのでメモ。

[1] CONFIG_LATENCYTOP と CONFIG_FTRACE を無効化

  Kernel hacking  --->
  [ ] Latency measuring infrastructure
  [ ] Tracers  ----

[2] CONFIG_KPROBES を無効化
  General setup  --->
  [ ] Kprobes

[3] KALLSYMS_ALL がようやく変更可能になるので無効化
  General setup  --->
  -*- Configure standard kernel features (expert users)  --->
  [ ]   Load all symbols for debugging/ksymoops

◆おまけ3
dtb (device tree blob)
ファイルは dts (device tree source)ファイルから生成されますが、dtb ファイルから dts ファイルに戻す事もできます。
Linux ツリーの中に dtc (device tree compiler)が入っています。

下記、コマンドで dtb ファイルから dts ファイルを取得できます。
$ cd /home/mint/raspi/
$ linux/scripts/dtc/dtc -I dtb -O dts ./bcm2708-rpi-b-plus.dtb > ./out.dts

Raspbian(2015-02)の環境を構築する

Raspbian が何やら新しいバージョンになっているようなので、環境を構築し直してみようと思います。

以下、以前に書いたここや、このあたりを参考にしつつ再構築しました。
(おおっ!? 備忘録として役立っているではないですか)

設定順序等を再構成し、いろいろ補完を行ないリメイクしました。
細かーい説明とかは端折ったりしてるかも。以前の記事も参照のこと。。。

◆新バージョン Raspbian の書き込み
http://www.raspberrypi.org/downloads/ から Raspbian のイメージファイル(2015-02-16-raspbian-wheezy.zip)をダウンロードし、Win32DiskImager (http://sourceforge.jp/projects/sfnet_win32diskimager/) により、microSD に書き込みます。
(とりあえず今回は4GBのmicroSDを使用しました。)

◆初期設定
書き込み後、最初の起動時に、コンフィグレーション画面が立ち上がりますので、

  microSDのパーティションの拡張。
1 Expand Filesystem

  タイムゾーンに日本(東京)を選択。
4 Internationalisation Options
->I2 Change Timezon
  ->Asia
    ->Tokyo

  キーボードレイアウトに日本語キーボードを選択。
4 Internationalisation Options
->I3 Change Keyboard Layout
  ->Generic 105-key (intl) PC
    ->Other
      ->Japanese
        ->Japanese - Japanese (OADG 109A)
    ->The default for the keyboard layout
      ->No compose key
        ->Yes

  オーバークロック(お好みで)
7 Overclock
->Medium

◆不要パッケージの削除

下記がインストール直後の状態です。1GB弱しか空きがありません。
$ df
Filesystem     1K-blocks    Used Available Use% Mounted on
rootfs           3671884 2479420    993104  72% /
/dev/root        3671884 2479420    993104  72% /
devtmpfs          218604       0    218604   0% /dev
tmpfs              44576     232     44344   1% /run
tmpfs               5120       0      5120   0% /run/lock
tmpfs              89140       0     89140   0% /run/shm
/dev/mmcblk0p1     57288   14720     42568  26% /boot
基本的には以前、に削除したのと同じパッケージを削除しました。(お好みでどうぞ)
何個か追加で削除してますが。(回路シミュレータの smartsim とか。。。)
(インストールされているパッケージは "dpkg -l" で確認できます。)
$ sudo apt-get autoremove -y wolfram-engine scratch sonic-pi
$ sudo apt-get autoremove -y python-minecraftpi python-pygame
$ sudo apt-get autoremove -y idle idle3
$ sudo apt-get autoremove -y netsurf-common dillo
$ sudo apt-get autoremove -y smartsim
$ sudo apt-get autoremove -y pistore debian-reference-common
$ sudo apt-get autoremove -y libraspberrypi-doc

$ sudo apt-get autoremove -y man manpages man-db
$ sudo apt-get autoremove -y git git-man
$ sudo apt-get autoremove -y galculator
$ sudo apt-get autoremove -y weston
$ sudo apt-get autoremove -y gdb gdbserver
$ rm -rf /home/pi/python_games/
$ sudo rmdir /usr/local/games/ /usr/games/

それなりに空きが出来たと思います。

$ df
Filesystem     1K-blocks    Used Available Use% Mounted on
rootfs           3671884 1770044   1702480  52% /
/dev/root        3671884 1770044   1702480  52% /
devtmpfs          218604       0    218604   0% /dev
tmpfs              44576     232     44344   1% /run
tmpfs               5120       0      5120   0% /run/lock
tmpfs              89140       0     89140   0% /run/shm
/dev/mmcblk0p1     57288   14720     42568  26% /boot

◆ファームウェア・カーネル/パッケージのアップデート
2015-02-16-raspbian-wheezy のカーネルバージョンは 3.18.7 のようです。
$ uname -r
3.18.7+
/boot の下を見てみると、デバイスツリーのファイル等が以前より増えています。
(あんまりデバイスツリー好きじゃないんですが、、、世の中の流れですね。。。)

ファームウェアのアップデートを行い、完了後リブートします。
$ sudo rpi-update
$ sudo reboot
リブート後、ちゃんとカーネルバージョンが変わっています。
$ uname -r
3.18.9+

古いバージョンのモジュールは不要なので、削除しておきます。
$ sudo rm -rf /lib/modules/3.18.7+/ /lib/modules/3.18.7-v7+/

サンプルプログラムも削除します。(お好みで。ビルドして一度サンプルを実行してみてもいいと思います。)
$ sudo rm -rf /opt/vc/src/hello_pi/

その他のパッケージもアップデートします。

$ sudo apt-get update
$ sudo apt-get upgrade

まだ半分くらいの空きがあります。
$ df
Filesystem     1K-blocks    Used Available Use% Mounted on
rootfs           3671884 1766000   1706524  51% /
/dev/root        3671884 1766000   1706524  51% /
devtmpfs          218644       0    218644   0% /dev
tmpfs              44584     244     44340   1% /run
tmpfs               5120       0      5120   0% /run/lock
tmpfs              89160       0     89160   0% /run/shm
/dev/mmcblk0p1     57288   14760     42528  26% /boot

◆sambaの初期設定
ネットワーク経由で Raspberry Pi とファイルのやりとりを行なうために、sambaの設定を行ないます。
(ホストマシンでクロスビルドしたカーネルイメージを持ってくるためです。)

$ sudo apt-get install samba chkconfig

    /etc/samba/smb.conf を編集。
[global]
dos charset = CP932
unix charset = UTF-8

ファイル末尾に以下を追加。
    : (略)
[pi]

path = /home/pi
writable = yes
guest ok = yes
browsable = yes
force user = pi
create mode = 0777
direcory mode = 0777

次回は 2015-02-16-raspbian-wheezy 用のLinuxカーネルを差し替えます。

演算子/errno/シグナル/システムコール 一覧表

プログラム、Linux 関連の各種テーブル早見表。

Linux カーネルのソースコードは↓下記サイトで確認可能。
  https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/

  https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/

表の作成は↓下記サイトにお世話になりました。
http://styleme.jp/tool/xls2html/

◆演算順序(C言語)

優先度 演算子 説明 評価順序
1 ( ) 括弧
[ ] 配列要素
. メンバ参照演算子
-> アロー演算子
2 & アドレス演算子
* 間接演算子
~ ビット反転
! 論理否定
+ プラス符号
- マイナス符号
++ インクリメント
-- デクリメント
sizeof サイズ
(cast) キャスト
3 * 乗算
/ 除算
% 剰余
4 + 加算
- 減算
5 << 左シフト
>> 右シフト
6 < より小さい
<= 以下
> より大きい
>= 以上
7 == 等しい
!= 等しくない
8 & ビット論理積
9 ^ ビット排他的論理和
10 | ビット論理和
11 && 論理積
12 || 論理和
13 ? : 三項演算子
14 = 代入演算子
*=
/=
%=
+=
-=
<<=
>>=
^=
&=
|=
15 , コンマ演算子

◆Linux errno
linux 3.19.3 の下記ファイルを参照し、作成。
- include/uapi/asm-generic/errno-base.h
- include/uapi/asm-generic/errno.h
- include/linux/errno.h

エラー番号 マクロ
コメント
1 EPERM Operation not permitted
2 ENOENT No such file or directory
3 ESRCH No such process
4 EINTR Interrupted system call
5 EIO I/O error
6 ENXIO No such device or address
7 E2BIG Argument list too long
8 ENOEXEC Exec format error
9 EBADF Bad file number
10 ECHILD No child processes
11 EAGAIN Try again
12 ENOMEM Out of memory
13 EACCES Permission denied
14 EFAULT Bad address
15 ENOTBLK Block device required
16 EBUSY Device or resource busy
17 EEXIST File exists
18 EXDEV Cross-device link
19 ENODEV No such device
20 ENOTDIR Not a directory
21 EISDIR Is a directory
22 EINVAL Invalid argument
23 ENFILE File table overflow
24 EMFILE Too many open files
25 ENOTTY Not a typewriter
26 ETXTBSY Text file busy
27 EFBIG File too large
28 ENOSPC No space left on device
29 ESPIPE Illegal seek
30 EROFS Read-only file system
31 EMLINK Too many links
32 EPIPE Broken pipe
33 EDOM Math argument out of domain of func
34 ERANGE Math result not representable
35 EDEADLK Resource deadlock would occur
36 ENAMETOOLONG File name too long
37 ENOLCK No record locks available
38 ENOSYS Function not implemented
39 ENOTEMPTY Directory not empty
40 ELOOP Too many symbolic links encountered
EAGAIN(11) EWOULDBLOCK Operation would block
42 ENOMSG No message of desired type
43 EIDRM Identifier removed
44 ECHRNG Channel number out of range
45 EL2NSYNC Level 2 not synchronized
46 EL3HLT Level 3 halted
47 EL3RST Level 3 reset
48 ELNRNG Link number out of range
49 EUNATCH Protocol driver not attached
50 ENOCSI No CSI structure available
51 EL2HLT Level 2 halted
52 EBADE Invalid exchange
53 EBADR Invalid request descriptor
54 EXFULL Exchange full
55 ENOANO No anode
56 EBADRQC Invalid request code
57 EBADSLT Invalid slot
EDEADLK(35) EDEADLOCK
59 EBFONT Bad font file format
60 ENOSTR Device not a stream
61 ENODATA No data available
62 ETIME Timer expired
63 ENOSR Out of streams resources
64 ENONET Machine is not on the network
65 ENOPKG Package not installed
66 EREMOTE Object is remote
67 ENOLINK Link has been severed
68 EADV Advertise error
69 ESRMNT Srmount error
70 ECOMM Communication error on send
71 EPROTO Protocol error
72 EMULTIHOP Multihop attempted
73 EDOTDOT RFS specific error
74 EBADMSG Not a data message
75 EOVERFLOW Value too large for defined data type
76 ENOTUNIQ Name not unique on network
77 EBADFD File descriptor in bad state
78 EREMCHG Remote address changed
79 ELIBACC Can not access a needed shared library
80 ELIBBAD Accessing a corrupted shared library
81 ELIBSCN .lib section in a.out corrupted
82 ELIBMAX Attempting to link in too many shared libraries
83 ELIBEXEC Cannot exec a shared library directly
84 EILSEQ Illegal byte sequence
85 ERESTART Interrupted system call should be restarted
86 ESTRPIPE Streams pipe error
87 EUSERS Too many users
88 ENOTSOCK Socket operation on non-socket
89 EDESTADDRREQ Destination address required
90 EMSGSIZE Message too long
91 EPROTOTYPE Protocol wrong type for socket
92 ENOPROTOOPT Protocol not available
93 EPROTONOSUPPORT Protocol not supported
94 ESOCKTNOSUPPORT Socket type not supported
95 EOPNOTSUPP Operation not supported on transport endpoint
96 EPFNOSUPPORT Protocol family not supported
97 EAFNOSUPPORT Address family not supported by protocol
98 EADDRINUSE Address already in use
99 EADDRNOTAVAIL Cannot assign requested address
100 ENETDOWN Network is down
101 ENETUNREACH Network is unreachable
102 ENETRESET Network dropped connection because of reset
103 ECONNABORTED Software caused connection abort
104 ECONNRESET Connection reset by peer
105 ENOBUFS No buffer space available
106 EISCONN Transport endpoint is already connected
107 ENOTCONN Transport endpoint is not connected
108 ESHUTDOWN Cannot send after transport endpoint shutdown
109 ETOOMANYREFS Too many references: cannot splice
110 ETIMEDOUT Connection timed out
111 ECONNREFUSED Connection refused
112 EHOSTDOWN Host is down
113 EHOSTUNREACH No route to host
114 EALREADY Operation already in progress
115 EINPROGRESS Operation now in progress
116 ESTALE Stale file handle
117 EUCLEAN Structure needs cleaning
118 ENOTNAM Not a XENIX named type file
119 ENAVAIL No XENIX semaphores available
120 EISNAM Is a named type file
121 EREMOTEIO Remote I/O error
122 EDQUOT Quota exceeded
123 ENOMEDIUM No medium found
124 EMEDIUMTYPE Wrong medium type
125 ECANCELED Operation Canceled
126 ENOKEY Required key not available
127 EKEYEXPIRED Key has expired
128 EKEYREVOKED Key has been revoked
129 EKEYREJECTED Key was rejected by service
130 EOWNERDEAD Owner died
131 ENOTRECOVERABLE State not recoverable
132 ERFKILL Operation not possible due to RF-kill
133 EHWPOISON Memory page has hardware error
512 ERESTARTSYS
513 ERESTARTNOINTR
514 ERESTARTNOHAND restart if no handler..
515 ENOIOCTLCMD No ioctl command
516 ERESTART_RESTARTBLOCK restart by calling sys_restart_syscall
517 EPROBE_DEFER Driver requests probe retry
518 EOPENSTALE open found a stale dentry
519
-

520
-

521 EBADHANDLE Illegal NFS file handle
522 ENOTSYNC Update synchronization mismatch
523 EBADCOOKIE Cookie is stale
524 ENOTSUPP Operation is not supported
525 ETOOSMALL Buffer or request is too small
526 ESERVERFAULT An untranslatable error occurred
527 EBADTYPE Type not supported by server
528 EJUKEBOX Request initiated, but will not complete before timeout
529 EIOCBQUEUED iocb queued, will get completion event


◆シグナル
linux 3.19.3 の下記ファイルを参照し、作成。
- include/uapi/asm-generic/signal.h

シグナル番号 マクロ 備考
1 SIGHUP
2 SIGINT
3 SIGQUIT
4 SIGILL
5 SIGTRAP
6 SIGABRT / SIGIOT
7 SIGBUS
8 SIGFPE
9 SIGKILL マスク不可
10 SIGUSR1
11 SIGSEGV
12 SIGUSR2
13 SIGPIPE
14 SIGALRM
15 SIGTERM
16 SIGSTKFLT
17 SIGCHLD
18 SIGCONT
19 SIGSTOP マスク不可
20 SIGTSTP
21 SIGTTIN
22 SIGTTOU
23 SIGURG
24 SIGXCPU
25 SIGXFSZ
26 SIGVTALRM
27 SIGPROF
28 SIGWINCH
29 SIGIO /*SIGLOST*/
SIGIO(29) SIGPOLL
30 SIGPWR
31 SIGSYS / SIGUNUSED

◆Linux システムコール
linux 3.19.3 の下記ファイルを参照し作成。
- arch/arm/include/uapi/asm/unistd.h

システムコール番号 シンボル
コメント
0 restart_syscall
1 exit
2 fork
3 read
4 write
5 open
6 close
7 - 7 was sys_waitpid
8 creat
9 link
10 unlink
11 execve
12 chdir
13 time
14 mknod
15 chmod
16 lchown
17 - 17 was sys_break
18 - 18 was sys_stat
19 lseek
20 getpid
21 mount
22 umount
23 setuid
24 getuid
25 stime
26 ptrace
27 alarm
28 - 28 was sys_fstat
29 pause
30 utime
31 - 31 was sys_stty
32 - 32 was sys_gtty
33 access
34 nice
35 - 35 was sys_ftime
36 sync
37 kill
38 rename
39 mkdir
40 rmdir
41 dup
42 pipe
43 times
44 - 44 was sys_prof
45 brk
46 setgid
47 getgid
48 - 48 was sys_signal
49 geteuid
50 getegid
51 acct
52 umount2
53 - 53 was sys_lock
54 ioctl
55 fcntl
56 - 56 was sys_mpx
57 setpgid
58 - 58 was sys_ulimit
59 - 59 was sys_olduname
60 umask
61 chroot
62 ustat
63 dup2
64 getppid
65 getpgrp
66 setsid
67 sigaction
68 - 68 was sys_sgetmask
69 - 69 was sys_ssetmask
70 setreuid
71 setregid
72 sigsuspend
73 sigpending
74 sethostname
75 setrlimit
76 getrlimit Back compat 2GB limited rlimit
77 getrusage
78 gettimeofday
79 settimeofday
80 getgroups
81 setgroups
82 select
83 symlink
84 - 84 was sys_lstat
85 readlink
86 uselib
87 swapon
88 reboot
89 readdir
90 mmap
91 munmap
92 truncate
93 ftruncate
94 fchmod
95 fchown
96 getpriority
97 setpriority
98 - 98 was sys_profil
99 statfs
100 fstatfs
101 - 101 was sys_ioperm
102 socketcall
103 syslog
104 setitimer
105 getitimer
106 stat
107 lstat
108 fstat
109 - 109 was sys_uname
110 - 110 was sys_iopl
111 vhangup
112 - 112 was sys_idle
113 syscall syscall to call a syscall!
114 wait4
115 swapoff
116 sysinfo
117 ipc
118 fsync
119 sigreturn
120 clone
121 setdomainname
122 uname
123 - 123 was sys_modify_ldt
124 adjtimex
125 mprotect
126 sigprocmask
127 - 127 was sys_create_module
128 init_module
129 delete_module
130 - 130 was sys_get_kernel_syms
131 quotactl
132 getpgid
133 fchdir
134 bdflush
135 sysfs
136 personality
137 - 137 was sys_afs_syscall
138 setfsuid
139 setfsgid
140 _llseek
141 getdents
142 _newselect
143 flock
144 msync
145 readv
146 writev
147 getsid
148 fdatasync
149 _sysctl
150 mlock
151 munlock
152 mlockall
153 munlockall
154 sched_setparam
155 sched_getparam
156 sched_setscheduler
157 sched_getscheduler
158 sched_yield
159 sched_get_priority_max
160 sched_get_priority_min
161 sched_rr_get_interval
162 nanosleep
163 mremap
164 setresuid
165 getresuid
166 - 166 was sys_vm86
167 - 167 was sys_query_module
168 poll
169 nfsservctl
170 setresgid
171 getresgid
172 prctl
173 rt_sigreturn
174 rt_sigaction
175 rt_sigprocmask
176 rt_sigpending
177 rt_sigtimedwait
178 rt_sigqueueinfo
179 rt_sigsuspend
180 pread64
181 pwrite64
182 chown
183 getcwd
184 capget
185 capset
186 sigaltstack
187 sendfile
188 - 188 reserved
189 - 189 reserved
190 vfork
191 ugetrlimit SuS compliant getrlimit
192 mmap2
193 truncate64
194 ftruncate64
195 stat64
196 lstat64
197 fstat64
198 lchown32
199 getuid32
200 getgid32
201 geteuid32
202 getegid32
203 setreuid32
204 setregid32
205 getgroups32
206 setgroups32
207 fchown32
208 setresuid32
209 getresuid32
210 setresgid32
211 getresgid32
212 chown32
213 setuid32
214 setgid32
215 setfsuid32
216 setfsgid32
217 getdents64
218 pivot_root
219 mincore
220 madvise
221 fcntl64
222 - 222 for tux
223 - 223 is unused
224 gettid
225 readahead
226 setxattr
227 lsetxattr
228 fsetxattr
229 getxattr
230 lgetxattr
231 fgetxattr
232 listxattr
233 llistxattr
234 flistxattr
235 removexattr
236 lremovexattr
237 fremovexattr
238 tkill
239 sendfile64
240 futex
241 sched_setaffinity
242 sched_getaffinity
243 io_setup
244 io_destroy
245 io_getevents
246 io_submit
247 io_cancel
248 exit_group
249 lookup_dcookie
250 epoll_create
251 epoll_ctl
252 epoll_wait
253 remap_file_pages
254 - 254 for set_thread_area
255 - 255 for get_thread_area
256 set_tid_address
257 timer_create
258 timer_settime
259 timer_gettime
260 timer_getoverrun
261 timer_delete
262 clock_settime
263 clock_gettime
264 clock_getres
265 clock_nanosleep
266 statfs64
267 fstatfs64
268 tgkill
269 utimes
270 arm_fadvise64_64
271 pciconfig_iobase
272 pciconfig_read
273 pciconfig_write
274 mq_open
275 mq_unlink
276 mq_timedsend
277 mq_timedreceive
278 mq_notify
279 mq_getsetattr
280 waitid
281 socket
282 bind
283 connect
284 listen
285 accept
286 getsockname
287 getpeername
288 socketpair
289 send
290 sendto
291 recv
292 recvfrom
293 shutdown
294 setsockopt
295 getsockopt
296 sendmsg
297 recvmsg
298 semop
299 semget
300 semctl
301 msgsnd
302 msgrcv
303 msgget
304 msgctl
305 shmat
306 shmdt
307 shmget
308 shmctl
309 add_key
310 request_key
311 keyctl
312 semtimedop
313 vserver
314 ioprio_set
315 ioprio_get
316 inotify_init
317 inotify_add_watch
318 inotify_rm_watch
319 mbind
320 get_mempolicy
321 set_mempolicy
322 openat
323 mkdirat
324 mknodat
325 fchownat
326 futimesat
327 fstatat64
328 unlinkat
329 renameat
330 linkat
331 symlinkat
332 readlinkat
333 fchmodat
334 faccessat
335 pselect6
336 ppoll
337 unshare
338 set_robust_list
339 get_robust_list
340 splice
341 arm_sync_file_range sync_file_range2
342 tee
343 vmsplice
344 move_pages
345 getcpu
346 epoll_pwait
347 kexec_load
348 utimensat
349 signalfd
350 timerfd_create
351 eventfd
352 fallocate
353 timerfd_settime
354 timerfd_gettime
355 signalfd4
356 eventfd2
357 epoll_create1
358 dup3
359 pipe2
360 inotify_init1
361 preadv
362 pwritev
363 rt_tgsigqueueinfo
364 perf_event_open
365 recvmmsg
366 accept4
367 fanotify_init
368 fanotify_mark
369 prlimit64
370 name_to_handle_at
371 open_by_handle_at
372 clock_adjtime
373 syncfs
374 sendmmsg
375 setns
376 process_vm_readv
377 process_vm_writev
378 kcmp
379 finit_module
380 sched_setattr
381 sched_getattr
382 renameat2
383 seccomp
384 getrandom
385 memfd_create
386 bpf
387 execveat

シェルスクリプト/Makefile/LKM 等サンプル

各種プログラム、Makefile サンプル。

◆シェルサンプル
shell/test.sh
#!/bin/bash

# ./test.sh 1 "2 3" 4

TMPFILE=/tmp/test

init() {
        if [ -f ${TMPFILE} ]; then
                rm -f ${TMPFILE}
        elif [ -e ${TMPFILE} ]; then
                exit 1
        fi

        touch ${TMPFILE}
        if [ $? -ne 0 ]; then
                exit 1
        fi
}

main() {
        local arg
        local i=0

        for arg in "$@"; do
                echo ${arg} >> ${TMPFILE}
                list[${i}]=${arg}
                i=$((${i} + 1))
        done

        i=0
        while [ ${i} -lt ${#list[@]} ]; do
                echo ${list[${i}]}
                i=$((${i} + 1))
        done

        list2=(`cat ${TMPFILE}`)
        for i in "${list[@]}"; do
                echo ${i}
        done

        while read line; do
                echo ${line}
        done < ${TMPFILE}
}

init
main "$@"

◆Makefileサンプル
csrc/Makefile

CC=gcc
CFLAGS ?= -O2 -Wall
LDFLAGS ?=

OBJS=main.o
TARGET=test

.PHONY: all clean
all: $(TARGET)

$(TARGET): $(OBJS)
        $(CC) -o $@ $^ $(LDFLAGS)

debug:
        $(MAKE) -C . CFLAGS="$(CFLAGS) -DDEBUG"

.c.o:
        $(CC) -c $< $(CFLAGS)

clean:
        $(RM) $(TARGET) $(OBJS)
上記サンプル↓
$ curl -O http://sstea.blog.jp/raspi/csrc/Makefile

csrc/main.c

#include <stdio.h>

#ifdef DEBUG
#define DEBUG(...)    printf("<DEBUG> " __VA_ARGS__)
#else /* !DEBUG */
#define DEBUG(...)    do { } while (0)
#endif /* !DEBUG */

int main(int argc, char **argv)
{
    DEBUG("hello\n");
    return 0;
}

◆Linux LKM(ローダブルカーネルモジュール)サンプル
kbuild/Makefile (KDIR は場合によっては任意に変更)
obj-y := test/

KDIR ?= /lib/module/$(shell uname -r)/build
PWD := $(shell pwd)

EXTRA_CFLAGS =

modules:
    make -C $(KDIR) M=$(PWD) V=1 modules

clean:
    make -C $(KDIR) M=$(PWD) V=1 clean
上記サンプル↓
$ curl -O http://sstea.blog.jp/raspi/kbuild/Makefile

kbuild/test/Makefile
obj-m:= test.o

test-objs := test_base.o
test-objs に.oファイルを複数指定することで、複数ファイルから1つのローダブルカーネルモジュール(.koファイル)を作成可能。

kbuild/test/test_base.c
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>

static int __init test_init(void)
{
    printk("test_init\n");
    return 0;
}
module_init(test_init);

static void __exit test_exit(void)
{
    printk("test_exit\n");
}
module_exit(test_exit);

はじめてのスマホ(環境構築週間)

◆Xperia Z3 スマホ環境、構築中...

とりあえずスマホを買ったので、買った当日中に、最低限、電話とメールだけは試行しておきました。
仕事に支障出るとまずいので。
あと、Wifi の設定。
家のネットインフラはほぼ有線オンリーなんで、追々、調べて設定見直します。

次に手を付けたのが、通信関連とバッテリー関連。
一応、一ヶ月の通信量に制限かけられてるので、何をしたらどれくらいの通信量になるか、感覚を知るために。
バッテリーも、何をしたらどれくらい減るものなのか、感覚を知るために。
(ガラケー生活が長かったので、、、)

いろいろ調べた結果、「通信量モニター」というのと「Battery Mix」というのを入れてみる。

特に深くは考えずにアンチウィルスソフトはAVGのを入れときました。
ファイラーは何個見てみましたがESファイルエクスプローラーが自分には合いそうと思ったのでこれを入れました。

いろいろ不要そうなプリインストールアプリはアンインストール、または無効化。

◆リモートデスクトップAndroidアプリ
あとはいざと言う時のために、外から家PCに繋ぎたいので、リモートデスクトップアプリを選定中。。。

リモートデスクトップ用のポート番号は変更済み。ルータのポートマッピングも設定済み。
他のPCからリモートデスクトップ出来るのは確認済みの環境。

以下、試してみた感想。
ホスト側でVLCで動画を再生してみてリモートデスクトップしてどれくらいリアルタイム性があるのか。

- Microsoft Remote Desktop
  本命。だったのだが、たまにカクツク。
  音も鳴るが、ちょいちょい飛ぶ。
  リモート中はホストマシンは操作できなくなる。(ログイン画面になる)

- Chrome リモート デスクトップ
  次の本命。結構サクサク動く。
  ポートとか空けてなくても外から普通に繋げそう。
  ただ、音が鳴らない。。。
  リモート中もホストマシンは変わらず操作できる。
  あと、家PCはデュアルディスプレイなので、リモート画面が横に凄く長い。
  (二画面並んだ画面が一画面としてスマホに表示される)

- PocketCloud リモートデスクトップ
  あまり印象に残っていない。
  カクツいたので、自分の中では候補から早々に消えた。

- Splashtop 2 Remote Desktop
  サクサク動く。音も鳴る。これいい!!
  リモート中もホストマシンは変わらず操作できる。
  「インターネット経由でのアクセス」は有料プラグイン(?)で対応、みたいな事書いてあったが、
  IPアドレスの入力設定をしたら、3G経由でも普通に繋がった。
  (ただし、よそのwifi(公衆無線LANスポットとか)からは無理でした。
    → 後日、VPN 環境を構築することで、公衆無線LANスポットからも繋がりました。)

聞いたことないソフトだったがSplashtopが第一候補。次点がGoogleのやつ、の二択になりました。

Raspberry Pi のディスクイメージをバックアップする

ここまで環境設定をいろいろやってきました。

しかし、機能的には何も嬉しい事をしてません。
ここからは、いろいろインストールしたりとかしようと思っていますが、一旦ここでこの環境をセーブしておきたいと思います。

何か失敗してやり直したいと思うかも知れませんし、ファイルシステム破損してしまった時とかに、再度環境構築するのは面倒くさいですし、、、

本当のところは、現在使っているclass 4のmicro SDカードからclass 10のmicro SDカードに引越してみて、起動時間がどうなるか見てみたい、というのが一番だったりするのですが。。。

単純にディスクイメージを吸い出すだけでもいいのですが、それだとmicroSDのサイズのディスクイメージが出来てしまいます。
(32GBのmicroSDを使用していると使用/未使用を問わず32GBのディスクイメージファイルになります。)
圧縮すれば未使用部分は縮むのですが、それでも個人的にはディスクイメージファイル自体に縮んでいて欲しいのです。(容量の小さいmicroSDに引越し出来ないし)

ディスクイメージの引越しについて、ディスクイメージを弄くり倒して行なう別解を用意しました。
(ホストマシンに直接カードリーダが繋げない、gparted使えない、などの環境でも引越し可能なはずです。)

◆ rootfs パーティションを縮小
まず、Linux ホストマシンに Raspberry Pi で使用していたmicroSDを挿します。
以前に Linux Mint の仮想環境をVirtualBoxで作成したので、今回はそれを使おうと思います。

Linux ホストマシンで gparted を使用します。ないならインストールします。
$ sudo apt-get install gparted

gparted を使用し、Raspberry Pi の rootfs パーティション(2個目のパーティション)を適当なサイズに縮小します。

ss_vbox_gparted

◆ ディスクイメージの出力
Raspberryp Pi 用microSD が /dev/sdb として認識されているものとして以下、記載します。

$ sudo fdisk -l /dev/sdb
とすると、
デバイス ブート      始点        終点     ブロック  Id  システム
/dev/sdb1            2048      262143      130048    6  FAT16
/dev/sdb2          262144     5439487     2588672   83  Linux
というように表示されたとします。
ここで、二個目のパーティションの終点の数値が最終セクタ番号になります。

なので、サイズとしては +1 した値を指定します。
$ sudo dd if=/dev/sdb of=/media/sf_shared/raspi.img count=5439488 bs=512
これでディスクイメージファイルが /media/sf_shared/raspi.img として出力されます。

◆ディスクイメージをマウントする
$ sudo kpartx -v -a /media/sf_shared/raspi.img
とすると、下記のような表示が出ると思います。
この時に表示された loop デバイスを使用します。(この例では loop0 を使用します)
add map loop0p1 (252:0): 0 260096 linear /dev/loop0 2048
add map loop0p2 (252:1): 0 5177344 linear /dev/loop0 262144

下記のようにすることで、Raspberry Pi 用のディスクイメージの rootfs パーティションを /mnt/ にマウントできます。
$ sudo mount /dev/mapper/loop0p2 /mnt/
◆ディスクイメージの中身を編集
せっかくマウントしたので、中をいじってみたいと思います。

bashの履歴ファイルを削除しておきましょう。
$ rm /mnt/home/pi/.bash_history
$ touch /mnt/home/pi/.bash_history

キャッシュもたぶん消しても大丈夫と思います。
(debconf ディレクトリは残しておいた方がよさそうです。apt 時に何かワーニング出ました。。。)
$ sudo rm -rf /mnt/var/cache/*
$ sudo mkdir /mnt/var/cache/debconf/

ディスクイメージの圧縮時に圧縮率が高まるように、未使用領域をゼロ埋めしておきます。
(下記のように実行することで空き容量がなくなるまで、中身が0で埋まったdummyというファイルを作成しています)
$ sudo dd if=/dev/zero of=/mnt/dummy bs=4096
$ sudo rm /mnt/dummy

◆ディスクイメージをアンマウントする

$ sudo umount /mnt/
$ sudo kpartx -d /media/sf_shared/raspi.img

◆おまけ1

Win32DiskImager で普通にディスクイメージを吸い出してもいいと思います。
上記を参考に、応用すれば必要部分のみのディスクイメージにすることが出来ます。

gparted は、コマンドラインで起動する場合、パラメータにデバイス意外にもイメージファイルを指定することができます。(イメージファイルの場合は、リサイズは出来ませんが...)
$ sudo gparted イメージファイル

また、下記のようにすることで、イメージファイルを必要部分のみ切り出すことができます。
$ sudo dd if=イメージ1 of=イメージ2 count=必要セクタ数 bs=512

◆おまけ2

ちにみにclass 4のmicro SDカードからclass 10のmicro SDカードに変えてみましたが、起動時間は3秒ほど早くなっただけでした。(もう少し期待してたんですが。)


今回作成したディスクイメージは dd コマンド、または Win32DiskImager で microSD に書き込むことで、環境をいつでもリストア出来ます。

次回からは、心おきなく Raspberry Pi をいじくることが出来ますね。

Raspberry Pi のカーネルをクロスビルドする

前回までは設定をいじってましたが、今回はLinuxカーネルを差し替えます。

こちらの記事で最新のRaspbianのカーネルを差し替えてますので、そちらも参考までに。

◆VirtualBox上でクロスコンパイルする

特にカーネルを差し替える必要はないのかもしれませんが、自己満足コンフィグレーションの最適化のため、何となく自家製Myカーネルに差し替えたいと思います。愛着もわきますし。

Raspberry Piのターゲット上でカーネルをビルドをすることも可能ですが、カーネルビルドするにはRaspberry Piでは非力で、とても時間がかかってしまうため、VirtualBox上に構築したLinux Mintでクロスコンパイルしようと思います。

VirtualBox上にLinux Mintの構築方法はこちらを参照。

以下はVirtualBox上のLinux Mintでの操作です。

◆Raspberry Pi用クロスコンパイラを取得する
コンパイラもカーネルソースもgitで公開されています。

  GitHub (https://github.com/raspberrypi/)

gitがインストールされていない場合は、インストールしておきます。
$ sudo apt-get install git

まずはTerminalを起動し、適当な作業ディレクトリを作成します。
以降、作業ディレクトリを ${HOME}/raspi/ として記述します。
$ cd ${HOME}/raspi/
$ git clone https://github.com/raspberrypi/tools.git

取得してきた中を見ると tools/arm-bcm2708/ に以下の4つのツールチェーンがあります。
- arm-bcm2708-linux-gnueabi
- arm-bcm2708hardfp-linux-gnueabi
- gcc-linaro-arm-linux-gnueabihf-raspbian
- gcc-linaro-arm-linux-gnueabihf-raspbian-x64

どれを使うべきか、、、
自分は 32bit版 Linux Mint をインストールしているので 64bit版はそもそも実行できません。
これで残りの候補は3つ。(64bitマシンならこれ一択でいい気もします)
それぞれの gcc で --version を実行した結果が下記です。
$ arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi-gcc --version
arm-bcm2708-linux-gnueabi-gcc (crosstool-NG 1.15.2) 4.7.1 20120402 (prerelease)
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ arm-bcm2708hardfp-linux-gnueabi/bin/arm-bcm2708hardfp-linux-gnueabi-gcc --version
arm-bcm2708hardfp-linux-gnueabi-gcc (crosstool-NG 1.15.2) 4.7.1 20120402 (prerelease)
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-gcc --version
arm-linux-gnueabihf-gcc (crosstool-NG linaro-1.13.1-4.8-2014.01 - Linaro GCC 2013.11) 4.8.3 20140106 (prerelease)
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
gcc-linaro-arm-linux-gnueabihf-raspbian がGCCバージョン4.8.3 で一番新しいので、これを使うことにします。
(安易ですが、OSSは最新であれば最新ほどいい、が自分のモットーですので。)

.bashrc の最後に
PATH=${HOME}/raspi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin:${PATH}
とでも付け加えて、パスを通しておきます。

# 新しいTerminalを使うか ". ~/.bashrc" と実行しないと、まだ反映はされていませんので注意。

◆Raspberry Pi用Linuxカーネルのソースコードを取得
$ cd ${HOME}/raspi/
$ git clone https://github.com/raspberrypi/linux.git
それなりに時間かかると思います。

◆Raspberry Pi用のカーネルコンフィグを最適化する
カーネルコンフィグは Raspberry Pi 上で
$ sudo zcat /proc/config.gz > raspi.config
とすれば、今 Raspberry Pi で動いているLinuxカーネルのカーネルコンフィグが取得できます。

今回は自分がデフォルトのコンフィグをベースに変更を加えたこのコンフィグを使用します。
カーネルバージョンは 3.12.31 です。

# もっと最新のカーネルがいいという方はもっと↓を参照。

変更点は下記の通りです。
- デバッグ関連のコンフィグを無効化
(ダンプ 吐かれても別に原因解析する気ないなー、と思ったのでCOREDUMP、GDB、KPROBEとか全部切ってます。)
- プロファイル関連のコンフィグを無効化
- IPv6 の無効化(元々ローダブルモジュールだったのでそのままでもいいのですが)
- ROOT_NFS の無効化
- カーネル圧縮形式をlz4に変更
- ログバッファサイズとかその他、何点か微修正

カーネルイメージの省サイズ化、及びオーバーヘッド軽減を目的としたものなので、デフォルトのコンフィグから機能的には変わっていないはずです。(nfs root を使用する場合を除き)

上記コンフィグを.config として linux ディレクトリ直下に置きます。
$ curl http://sstea.blog.jp/raspi/kbuild/kconfig-rpi-3.12.31 > .config

◆Raspberry Pi用のカーネルをビルド(再構築)する
今回、カーネル圧縮形式をlz4にしているので下記をインストールしておきます。
$ sudo apt-get install liblz4-tool

ついでに、カーネルビルドに必要なパッケージが未インストールなら入れておきます。
$ sudo apt-get install build-essential libncurses5-dev

環境変数を設定します。
$ export ARCH=arm
$ export CROSS_COMPILE=arm-linux-gnueabihf-
カーネルコンフィグを変えたい場合は変えます。(変えないならmenuconfigは不要です。)
$ cd ${HOME}/raspi/linux/
$ make menuconfig
カーネルをビルドします。
$ make
カーネルモジュールのビルド&インストールを行います。(インストール先はテンポラリなのでどこでもいいです。../mod-3.12.31である必要はありません。)
$ make modules
$ make modules_install INSTALL_MOD_PATH=../mod-3.12.31/  INSTALL_MOD_STRIP=--strip-unneeded

ビルドが完了したなら、linux/arch/arm/boot/zImage がカーネルイメージになります。
これを kernel.img とリネームし、Raspberry Pi の /boot/kernel.img と置換することで新カーネルに差し替えることが出来ます。

ちなみに、元のカーネルイメージはgzip圧縮形式で 3.3MBほどでした。
今回のカーネルイメージはlz4圧縮形式で3.0MBほどで、シュリンク出来ています。
(同じgizp圧縮形式なら2.6MBまで縮みましたが、展開速度が高速なlz4を採用しています。)

あと、${HOME}/raspi/mod-3.12.31/ というのが出来ているはずなのでこの中の lib/modules/3.12.31+/ をRaspberry Pi の /lib/modules/ 以下に置いてあげるのも忘れずに。

ちなみに、../mod-3.12.31/lib/firmware/ にもいろいろファイルが出来ているのですが、
Raspberry Pi の /lib/firmware/ にあるファイルと一つも被っていないのが謎。
たぶんなくてもいい気もしますが、念のために ../mod-3.12.31/lib/firmware/ 以下のファイルも Raspberry Pi の /lib/firmware/ 以下にコピーしておくことにします。

◆Raspberry Pi用のチャキチャキの最近カーネルを使用する
と、ここで終わってもいいのですが、せっかくビルドまでして自家製カーネルを使うのだから、最新バージョンのカーネルを使用したいと思います。
現在の最新バージョンは 3.17.2 ですので、3.17.2 のカーネルにしましょう。

git でLinuxカーネルのソースを取得する所までは同じです。
(または、3.12.31 のツリーが不要なら make distclean してそれを流用しましょう。)
$ cd ${HOME}/raspi/linux/
$ git checkout -b rpi-3.17.y remotes/origin/rpi-3.17.y

3.17.2 のカーネルコンフィグにはこのコンフィグを使用します。
デフォルトコンフィグからの変更点は 3.12.31 の時と同様です。

ビルド方法等は 3.12.31 と同様です。

カーネルイメージを差し替えて、リブート後 Raspberry Pi 上で
$ uname -r
とし、3.17.2 と表示されていれば成功です。

◆カーネルイメージのファイル名を変更する
今回はカーネルを自家製カーネルに置き換えました。
ファームアップデート等を行なうと、本家のカーネルイメージに置き換えられてしまいます。

カーネルイメージのファイル名をデフォルト(kernel.img) から変更することで、これを回避することができます。

/boot/config.txt に下記を追記します。
$ kernel=kernel-3.17.img

カーネルイメージのファイル名をリネームします。
$ sudo mv /boot/kernel.img /boot/kernel-3.17.img

◆おまけ1
カーネルのオーバーヘッド軽減を目指してカーネルコンフィグをいじりましたが、効果は出ているのでしょうか?

printk で表示できる時間はカーネル起動からの時間のため、カーネル省サイズ下によるブートローダーの展開時間削減の効果は残念ながら正確な確認方法がありません。(体感できるレベルでなければ)

カーネル起動後であればカーネルログで確認できますので、今回の確認方法としてはカーネルログのrootfsのマウントまでの時間("EXT4-fs (mmcblk0p2): re-mounted. Opts: (null)"とういうログの出力時間)を指標としたいと思います。
以前の記事でquietの効果確認を行なったのと同じ方法です。)

オリジナルconfig
raspberrypi kernel: [   13.000215] EXT4-fs (mmcblk0p2): re-mounted. Opts: (null)
変更config
raspberrypi kernel: [   12.670055] EXT4-fs (mmcblk0p2): re-mounted. Opts: (null)

一応オリジナルより早くなってそうです。体感できないと思いますが。
小さなことからコツコツと!!

◆おまけ2

initramfsを使用してみます。

# 結局使用しない構成に戻しましたが。

現状のブートシーケンスはbootloader→kernel→rootfsの順に起動しますが、
bootloader→kernel→initramfs→rootfsの順に起動させる事ができます。

このinitramfsで先に起動させておきたいデーモン等やモジュールのロード等を済ませれば、rootfsの起動スクリプトの処理が遅かろうが関係ありません。
$ sudo apt-get install initramfs-tools
$ sudo update-initramfs -c -k $(uname -r)
で /boot/ 以下に initrd.img-3.17.2+ というファイルが出来ているはずです。

/boot/config.txt に以下を追記すれば、initramfsを使用したブートシーケンスになります。
initramfs initrd.img-3.17.2+
ただこのままだと、純粋にinitramfsを経由するようになった分だけ起動時間が少し遅くなっただけでメリットはありません。

initramfsの中身をいじくるためにこのファイルを VirtualBox の Linux Mint 上に持っていきます。
以下は ${WORKDIR} にファイルを持ってきたとして記載します。

ファイル名を変更し、ディレクトリを作成しておきます。
$ mv initrd.img-3.17.2+ initrd.img-3.17.2+.orig.gz
$ mkdir -p ${WORKDIR}/initramfs/
展開します。
$ cd ${WORKDIR}/initramfs/
$ gunzip -c -9 ../initrd.img-3.17.2+.orig.gz | cpio -i -d -H newc
お好きにいじくってください。

満足したら、再びinitramfsイメージにします。
$ cd ${WORKDIR}/initramfs/
$ find . | cpio -o -H newc | gzip > ../initrd.img-3.17.2.+
これを raspberry pi の /boot/ 以下においてあげてください。


次回はいったんこの環境をバックアップしようと思います。

Raspberry Pi の更なる最適化を試みる

前回、いろいろな最適化にトライしました。
今回は更なる最適化をはかりたいと思います。

◆電源投入~カーネルまで


そもそもLinuxカーネルのログ出力が開始されるまでで、8秒程かかっているように感じます。
つまりLinuxカーネル到達前のブートローダ部分でそれだけかかっている?

NOOBS は便利で高機能ですが、それゆえに起動時間の足を引っ張っている可能性はあります。

以前の記事では NOOBS を使って Raspbian をインストールしましたが、NOOBS を経由せず Raspbian を起動させてみて、起動時間が短縮されるか見てみたいと思います。

http://www.raspberrypi.org/downloads/ から今度は Raspbian のイメージファイル(2014-09-09-wheezy-raspbian.zip)をダウンロードします。

Win32DiskImager (http://sourceforge.jp/projects/sfnet_win32diskimager/) をダンロード&インストールし、ダウンロードしたイメージファイルを展開し microSD 書き込みます。、

※ microSD の内容は全て消去されます。ご注意を!!


で、電源投入すると、、、
前より明らかに早いです!!

4秒くらいは早くLinuxカーネルに到達出来ている気がします。
パーティションも2個とスッキリしました。(NOOBSを使用したインストール時はパーティションが6個くらい出来ていました。)

こちらの環境をベース環境としたいと思います。
前記事で行なった初期設定最適化等を再度行ないます。。。(面倒くさいですが)

◆カーネル起動~ログインプロンプト表示まで

気を取り直して、、、

起動時にカーネルログがベロベロ出ますが、見てますか?特に見ませんよね?
なので、あのカーネルログ出力を抑制しようと思います。
下記のように、カーネルコマンドラインに quiet を追加するだけです。

/boot/cmdline.txt
dwc_otg.lpm_enable=0 console=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p6 rootfstype=ext4 elevator=deadline rootwait quiet
起動してみると、ログインプロンプト到達までが 1, 2秒短縮されたような気がします。

コンソールへの出力を抑制するだけで、内部的にはきちんとログ出力はされているので、
どうしても見たいという場合は
$ cat /var/log/syslog
とすれば、ブート時のカーネルログを確認することが出来ます。

実際に、/var/log/syslog 内のルートファイルシステムのマウント箇所のログが下記ですが、
quiet を付ける事で、ログ出力のタイミングが 1.3s 程早くなっている事が確認できます。
高速化は気のせいではなかったようです。よかった。よかった。

quiet なし
    : (略)
raspberrypi kernel: [   13.90288] EXT4-fs (mmcblk0p2): re-mounted. Opts: (null)
quiet あり
    : (略)
raspberrypi kernel: [   12.670055] EXT4-fs (mmcblk0p2): re-mounted. Opts: (null)

◆オーバークロック
早く動かしたいならクロックを早くする。道理です。真理です。
やはり手っ取り早いのはオーバークロックでしょう。
$ sudo raspi-config
で、"7 Overclock" を選択します。
とはいいつつも、不安定になっては元も子もないので、とりあえず中間のやつにしときます。
Medium 900MHz ARM, 250MHz core, 450MHz SDRAM, 2 overvolt

◆fsckチェックの抑制

起動時のfsckチェックを省いてみます。

/etc/fstab
proc            /proc           proc    defaults          0       0
/dev/mmcblk0p1  /boot           vfat    defaults          0       0
/dev/mmcblk0p2  /               ext4    defaults,noatime  0       0
tmpfs           /tmp            tmpfs   defaults,size=32m 0       0
tmpfs           /var/log        tmpfs   defaults,size=32m 0       0

リブートしてみましたが、、、
あんまり、早くなったような感じはないです。体感的には分かりません。

これは諸刃の剣でもあるので、ここは変更しなくてもいいかもしれません。
自分は、毎回でなくてもたまにfsckするくらいでいいかな、というのと、ファイルシステム破損に対しては"ディスクイメージ自体のバックアップ"で対処しようと思っていますので、このままで行ってみます。

◆起動時のスクリプトは...(よく分からないので)現状維持
起動時間のボトルネックの大半はユーザー空間の起動スクリプトのように(体感では)思いますが、あのあたりのスクリプトは何をしてるのか自分はよく分かってないので、今は触らずに置いておきます。今度は(もやは自己満足ですが)カーネルをいじくって最適化をはかりたいと思います。(自分はこっちが本業なので)

次回はカーネルを自前ビルドし、差し替えたいと思います。
プライバシーポリシー
当サイトでは、Googleを含む第三者配信事業者や広告ネットワークが配信する広告を掲載しています。
当サイトでは、アクセス情報に基づいた適切な広告表示、及びトラフィックデータ収集のためにCookieを使用しています。
ユーザーはCookieの無効化により、これらの情報の提供を拒否する事ができます。
スポンサーリンク
記事検索
スポンサーリンク