Articles
Java
Java技術関連記事
著者:Bill Courington、Gary Collins
2012年8月公開
Raspberry PiでLinuxとJava SE Embeddedを1時間以内に稼働させる方法
クレジット・カード程度の大きさで、Javaプログラミングに関する書籍1冊分ほどの費用しかかからないコンピュータ。
それが、Raspberry Piです。Raspberry Piはヘッドレス組込みアプリケーション向けの完全なJava SEランタイムをサポートしています。本記事では、Raspberry PiでJavaプログラミングを稼働させる方法について、次のトピックに従って説明します。
注:本記事の手順には他の方法を適用できる場合があります。特に、ホスト・コンピュータ(デスクトップまたはラップトップ)やRaspberry Piで直接実行する操作については様々な方法があります。知識や好みに応じて(さらに、Linuxのチューニングと微調整(オプション)の項のトピックを参照して)、自分に合ったワークフローを作成してください。
Raspberry Piは低電力の小型ボードです。ハードウェア浮動小数点演算が可能な700mHz ARMv6 CPUとグラフィック・プロセッサが1つのチップ上に統合されています。このグラフィック・プロセッサとCPUは256MBのRAMを共有します。USB、イーサネット、高精細グラフィック、オーディオ、SDカード、汎用I/Oのためのコネクタも搭載されています。図1は、Raspberry Pi model Bです。大きさがわかるように、SDカードを挿入しています。このSDカードは、Raspberry Piのブート元になるという特別な役割を担います。本記事の大部分は、ブート可能なSDカード内のファイルの作成や変更に関する手順の説明です。

図1.Raspberry Pi Model B
Raspberry Piの操作には、USBキーボードとUSBマウス、HDMIモニターまたはテレビ(最大1080p)を使用できます。また、ボードに搭載されているイーサネット接続を利用して、ネットワークに接続したホストからssh経由で操作することもできます。sshによるログインを有効にする方法については、本記事のLinuxのチューニングと微調整(オプション)の項で説明します。
Java SE Embeddedを実行できるようにRaspberry Pi model Bをセットアップするためには、次の環境を用意する必要があります。
wgetユーティリティなど)。
$ sudo apt-get install gparted電源を接続すると、SDカード・スロットからRaspberry Piファームウェアがブートします。Java SE EmbeddedはLinux上で稼働するため、まずはLinuxをSDカードに保存する作業を行います。
注:以下の手順はDebian Squeezeに対応しています。Raspberry Pi向けのその他のLinux実装もおそらく動作しますが、ARMチップのソフトウェア浮動小数点演算に対応するようにビルドされたLinux実装を使用する必要があります。Raspberry PiのWebサイトでリンクされている各種イメージは、ハードウェア浮動小数点演算に対応するようにビルドされている可能性があります。その場合はJava SE for Embeddedと連携できません。
Raspberry Pi向けのDebian Squeezeイメージ(ZIP形式)のリンクはhttp://elinux.org/RPi_Distributions#Debian_ARMです。ファイル・サイズは約450MBです。以降の手順は、~/RaspberryPiという新しいディレクトリにイメージをダウンロードしたと想定しています。ダウンロードしたファイルを検証するためには、ダウンロードの開始時に表示されるページのSHA-1チェックサムの確認手順に従ってください。
次のコマンドで、イメージを解凍します。
$ cd ~/RaspberryPi $ unzip *.zip
解凍すると、debian6-19-04-2012のような名称のサブディレクトリが作成されます。
ホスト・コンピュータで、SDカードのデバイス・ハンドルを次の手順で調べます(他の方法を使用してもかまいません)。
dmesg | tailを実行します。デバイスのマウント状況に関するメッセージが表示されます。関連する情報は、メッセージの最後の数行のみです。dmesg | tailを再度実行します。出力結果には、(最初に使用したウィンドウと比較して)新たにマウントしたSDカードに関連する行が追加されています。環境によって詳細情報は異なりますが、おおむね次のような出力結果となります。[ 110.084625] sdb: detected capacity change from 0 to 3963617280[ 118.055249] sd 2:0:0:0:[sdb] 7741440 512-byte logical blocks:(3.96 GB/3.69 GiB)[ 118.059409] sd 2:0:0:0:[sdb] Assuming drive cache: write through[ 118.064547] sd 2:0:0:0:[sdb] Assuming drive cache: write through[ 118.066015] sdb: sdb1sdbです。これはデバイス・ハンドルの/dev/sdbを表しています。また、sdb1は、この例で使用しているカードの単一パーティションを表します。カードは複数のパーティションに分割されている場合もあります。以降の手順では、SDカードのデバイス・ハンドルが/dev/sdbで、sdb1という単一パーティションがあることを想定しています。必要に応じて、お使いの環境に合わせて手順を変更してください。
$ sudo umount /dev/sdb1ddコマンドを使用して、DebianイメージをSDカードにコピーします。of)の値が正しく入力されていることを確認してください。このコマンドでは、すべてのデータを上書きする低レベルのディスク・コピーが実行されます。そのため、誤ったデバイスを指定した場合は、データが破損します。$ cd ~/RaspberryPi/debian6-19-04-2012$ sudo dd if=yourDebian.img of=/dev/sdb bs=1M1859+1 records in
1859+1 records out
1950000000 bytes (2.0 GB) copied, 212.344 s, 9.2MB/s ddコマンドの実行には時間がかかります。4GB Class 4カードの処理時間は5~10分程度です。また、ddでは進捗状況が示されないため、処理に時間がかかっていても、そのまま待機してください。この時点でSDカードのLinuxインストールが正しく動作することを確認する場合は、初回ブートの項を先に読んでから、SDカードのパーティションのサイズ変更に戻ってください。
現時点のSDカードには3つのパーティションと未割当て領域が含まれています。この未割当て領域をLinuxファイル・システムに追加して、Java SE Embeddedとアプリケーションを保存するための領域を増やします。未割当て領域をファイル・システムに割り当てるためには、SDカードのパーティションを修正します。具体的には、パーティションの1つを削除して再作成し、別のパーティションのサイズを変更します。
$ sudo gparted/dev/sdb上のパーティションと未割当て(unallocated)領域を表示します。
図2.初期状態のSDカード・パーティション
3つのパーティションはそれぞれ次のとおりです。
/dev/sdb1:ブート・パーティション/dev/sdb2:Linuxルート・ファイル・システム(1.5GBの割当て済み領域のほとんどがすでに使用中)/dev/sdb3:Linuxスワップ領域カード容量の約半分が未割当てです。空き領域のうちもっとも容量の大きい部分が/dev/sdb3パーティションの直後にあります。この領域を/dev/sdb2(ファイル・システム)に追加するために、一時的に/dev/sdb3を削除し、/dev/sdb2の領域を拡張してから、/dev/sdb3を再作成します。
/dev/sdb3」(linux-swap)を選択し、右クリックして「Delete」を選択します。パーティションが削除されたように表示されますが、この削除操作はキューに格納されていて、後で実行されます。
図3.削除操作をキューに格納した後のSDカード・パーティション
/dev/sdb2」(Linuxファイル・システム)を選択し、右クリックして「Resize/Move」を選択します。表示されるダイアログ・ボックスで、"Free space following"の値が512前後(またはスワップ用に残す任意の容量)になるまで、右側の矢印をドラッグします。512ちょうどにドラッグできない場合がありますが、数値を正確に合わせる必要はありません。
図4.スワップ用に512MBを確保した状態
図5.新しいスワップ・パーティション
図6.新しいパーティション・マップ
注:以下の手順では、モニター、キーボード、動作検証済みのイーサネット・ケーブルをRaspberry Piに接続しておく必要があります。
$ sudo /etc/rc.localRaspberryIPsshログインを許可します。$ sudo update-rc.d -f ssh defaults 20sshログインを有効化します。$ sudo sync; sudo shutdown -r now これで、ホスト・コンピュータからネットワーク経由でRaspberry PiのSDカードの読取りと書込みを実行できるようになりました。
本項では、ホスト・コンピュータを使用してJava SE Embeddedをダウンロードし、ネットワーク経由でRaspberry PiのLinuxファイル・システムにコピーします。そのままリモートでダウンロード・ファイルを解凍し、Javaを起動します。
図7.1つ目のダウンロード・リンク
図8.2つ目のダウンロード・リンク
.gzファイルをDownloadsディレクトリに保存します。$ ssh pi@RaspberryIP mkdir /home/pi/java$ scp ~/Downloads/*.gz pi@RaspberryIP:/home/pi/java$ ssh pi@RaspberryIP$ cd /home/pi/java$ tar -zxvf *.gz ... $ ls ejre*
ejre1.7.0_04
$ cd ejre*
$ ./bin/java -version
java version "1.7.0_04-ea"
Java(TM) SE Runtime Environment for Embedded (build 1.7.0_04-ea-b20, headless)
Java Hotspot(TM) Embedded Client VM (build 23.0-b21, mixed mode) $ rm /home/pi/java/*.gzここで説明する各種コマンドを実行することで、Raspberry Piシステムの信頼性、応答性、利便性を高めることができます。必要なコマンドを選択し、Raspberry Piに対して実行してください。また、問題が発生した場合の原因調査を容易にするために、変更を行うたびにリブートしてください。
本項の内容:
ネットワークで動的IPアドレスを再利用している場合は、静的IPアドレスへの変更を行う必要はありません。Raspberry PiのIPアドレスが結果的に同じものになるからです。ブートのたびにRaspberry Piの動的IPアドレスが変わる場合は、静的IPアドレスを設定する方がsshの実行に便利です。以下の手順では、Raspberry Piにraspberrypiというホスト名を割り当てることを想定しています。
スーパーユーザーとして、テキスト・エディタで/etc/hostsを開きます(例:sudo vi /etc/ hosts)。ネットワーク内で有効な静的IPアドレス、ドメイン名(オプション)、エイリアスで構成される行をRaspberry Pi用に追加します。Raspberry Piをホスト名raspberrypiとして指定した場合の実行例は次のとおりです。
127.0.0.1 localhostâ?¨192.168.0.100 raspberrypi.yourDomain raspberrypi loghost
ファイルを保存し、エディタを終了します。
スーパーユーザーとして、テキスト・エディタで/etc/hostnameを開きます。次の文字列を含む行を追加します。
raspberrypi
ファイルを保存し、エディタを終了します。
ネットワークの負荷が高まった場合に、オペレーティング・システムによりRaspberry Piの静的IPアドレスが変更され、静的IPアドレスを使用するsshなどの操作が停止するという問題が発生することがあります。次の手順を実行することで、そのような問題を防ぐことができます。
イーサネット・コントローラのハードウェア・アドレスを次のようにして調べます。
まず、イーサネット・コントローラの名称を確認します(xはそれぞれ、アドレスの数値を示します)。
$ ip a 1: lo:<LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo 2: eth0:<BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1488 qdisc pfifo_fast state UNKNOWN qlen 1000 link/ether b8:27:eb:b5:e8:90 brd ff:ff:ff:ff:ff:ff inet xx.xxx.xxx.xx/xx brd xx.xxx.xxx.xxx scope global eth0この例では、イーサネット・コントローラの名称は
eth0です。link/etherの後の16進数がハードウェア・アドレスで、この例ではb8:27:eb:b5:e8:90です。
イーサネット・コントローラのハードウェア・アドレスがわかったので、スーパーユーザーとして、テキスト・エディタで/etc/network/interfacesを開き、下に示す# New entriesコメントの後に記述されているように行を追加します(適宜、お使いのネットワークの詳細情報を当てはめてください)。
# Used by ifup(8) and ifdown(8).See the interfaces(5) manpage orâ?¨ # /usr/share/doc/ifupdown/examples for more information. auto lo iface lo inet loopback # # New entries to support static IP follow: auto eth0 iface eth0 inet static hwaddress ether b8:27:eb:b5:e8:90 address 192.168.0.100 network 192.168.0.0 netmask 255.255.255.0 broadcast 192.168.0.255 gateway 192.168.0.1
Debian Linuxではデフォルトでスワップが無効になっています。Raspberry PiのRAMのサイズ(256KB)を上回る容量の処理が実行された場合は、システムがクラッシュします。また、組込みアプリケーションでは最終アクセス日時はほとんど使用されないにもかかわらず、ファイル・システムではデフォルトで各ファイルの最終アクセス日時の記録に時間が費やされます。最終アクセス日時の記録はSDカードの寿命の低下にもつながります。これらのデフォルトの動作は/etc/fstabファイル内に指定されています。
スーパーユーザーとして、viなどのエディタで/etc/fstabを開きます。次のようなファイル内容が表示されます。
proc /proc proc defaults 0 0 /dev/mmcblk0p1 /boot vfat defaults 0 0 #/dev/mmcblk0p3 none swap sw 0 0
スワップを有効にするためには、3行目のコメントを外します。
注:SDカードに対するスワップは時間がかかります。組込みアプリケーションの場合は、スワップが発生しないようにメモリを管理する方法が望ましいでしょう。
最終アクセス日時の記録にかかるオーバーヘッドをなくすためには、p1とp3の間にp2マウント・ポイントを挿入します。挿入には、noatimeオプションとnodiratimeオプションを使用します。編集後のファイルは次のようになります。ファイルを保存してエディタを終了します。
proc /proc proc defaults 0 0 /dev/mmcblk0p1 /boot vfat defaults 0 0 /dev/mmcblk0p2 / auto rw,noatime,nodiratime,errors=remount-ro 0 1 /dev/mmcblk0p3 none swap sw 0 0
p3(ホスト上に/dev/sdb3として作成したスワップ・パーティション)をスワップ領域に割り当てます。
$ sudo mkswap /dev/mmcblk0p3
Raspberry Piはデフォルトで、ヨーロッパ/ロンドンのタイムゾーン、およびen_GB_UTF-8ロケールを使用するように構成されています。コンピュータの地域を変更するためには、次の手順を実行します。
タイムゾーンを変更するためには、次のコマンドを入力します。
$ sudo dpkg-reconfigure tzdata図9のような疑似グラフィカル・ユーザー・インタフェースが表示されます。
図9.タイムゾーンのユーザー・インタフェース
上矢印キーと下矢印キーを使用して選択カーソルを移動し、地域と都市を選択します。左矢印キーと右矢印キーを使用して<Ok>または<Cancel>を反転させ、[Return]キーを押します。
次のコマンドを実行してロケールを設定します。
$ sudo dpkg-reconfigure -p low locales
タイムゾーンの設定用のインタフェースに似たユーザー・インタフェースが表示されます。
ソフトウェア・パッケージのアップデートなどの多くの操作では、正しい日時が設定されていることが求められます。日時を自動的に設定するためには、ネットワーク内にあるタイム・サーバーのIDを調べて、次のコマンドを実行します。
$ sudo ntpdate yourNTPServerブートのたびに時刻を設定する場合は、スーパーユーザーとして
/etc/rc.localを編集し、スクリプトの終了前に次の行を追加します。
ntpdate yourNTPServer
www.lego.comなどのよく知られたインターネット・ホストに対してpingを実行します。ホストが応答しない場合は、ネットワークがプロキシの背後にあるかどうかを確認し、必要な場合は、お使いのネットワークの規則に従ってhttp_proxy環境変数を設定します。次に例を示します。
$ sudo export http_proxy =’http:192.168.0.1:3128’
ログインのたびにプロキシを設定する場合は、~/.bash_profile(別のシェルを使用している場合は同等の設定ファイル)にexportコマンドを追加します。
キーボードのキーの解釈が誤っている場合や、キーボードのレイアウトを変更する場合は、次のコマンドを使用します。
$ sudo dpkg-reconfigure keyboard-configuration
このユーザー・インタフェースは、本記事のタイムゾーンとロケールの設定の項で説明したインタフェースと似ています。
Debianと共に配布されるパッケージをアップデートする前に、スーパーユーザーとして、テキスト・エディタで/etc/apt/sources.listを開きます。このファイルには、新しいパッケージやアップデート後のパッケージを格納するリポジトリの場所が記載されています。配布時には、リポジトリの場所を示すURLにftp.ukが含まれています。イギリス以外の地域では、これらのエントリを地理的に近い場所に変更することでパフォーマンスを向上できます。たとえば、米国の場合は、すべてのURLのftp.ukをftp.usに変更できます。Debianのリポジトリの場所に関する情報は、http://ftp.debian.org/debian/README.mirrors.htmlにあります。
インストール済みのパッケージをアップデートするためには、Raspberry Piがインターネットに接続されていることを確認し、次のコマンドを入力します。
$ sudo apt-get update $ sudo apt-get upgrade
パッケージ・リスト内に重複したエントリがあるというメッセージが表示された場合は、エディタで再度/etc/apt/sources.listを開き、重複したエントリをコメントアウトします。通常は、一番多くの情報が含まれるエントリを残すと良いでしょう。
Raspberry Piにローカルでログインしたときにウィンドウ・システムを自動的に起動する場合は、デフォルトの実行レベルを次のように変更します。スーパーユーザーとして、テキスト・エディタで/etc/inittabを開きます。次のエントリを探します。
# The default runlevel. id:2:initdefault:実行レベルを5に変更します。
# The default runlevel. id:5:initdefault:注:グラフィックを使用するとRaspberry PiのRAMが大量に消費されます(約90MB)。
デフォルト・ブラウザのMidoriで問題が発生する場合は、Iceweaselを試してください。
$ sudo apt-get update $ sudo apt-get install iceweasel
Raspberry Piのサウンド出力はデフォルトでは無効になっています。スーパーユーザーとして、テキスト・エディタで/etc/modulesを開きます。ファイルの末尾に次の行を追加します。
snd_bcm2835
ファイルを保存して閉じます。Raspberry Piのリブート後、サウンドが有効になります。