Armadilloが動作する仕組み

前章で実際にArmadilloを動かしてみて、Armadilloとはどのようなコンピューターなのか、大体のイメージが掴めたと思います。

この章では、Armadilloがどのようなソフトウェアで構成されていて、それらがどのように動いているのか、その仕組みを詳しく説明していきます。

5.1. ソフトウェア構成

Armadilloは、以下のソフトウェアによって動作します。

5.1.1. ブートローダー

ブートローダーは、電源投入後、最初に動作するソフトウェアです。Armadillo-400シリーズではHermit-Atブートローダー(以降、単にHermit-Atと記述します)を使用します。

Hermit-Atは、最低限の初期化処理を行った後、カーネルをブートします。Hermit-Atの動作については、「カーネルが動作するまで」で詳しく説明します。

5.1.2. Linuxカーネル

Armadillo-400シリーズでは、標準のカーネルとしてLinux 2.6系を使用します。

標準ではカーネルイメージはフラッシュメモリのカーネルリージョンに配置されます。カーネルイメージは、Hermit-Atのブートオプションを変更することで、ストレージ(microSD)またはTFTPサーバー上にも配置することができます。

Linuxカーネルは、プロセス管理(スケジューリング)、時間管理、メモリ管理、デバイスドライバ、プロトコルスタック、ファイルシステムなどのOSとしてのコア機能を提供します。Linuxカーネルは、ユーザーランドで動作するプログラムとの唯一のAPIとして、システムコールを提供します。ユーザーランドのプログラムは、必ずシステムコールを通してカーネルの機能を呼び出します。

Linuxカーネルの初期化処理については、「カーネルの初期化処理」で詳しく説明します。

5.1.3. ユーザーランド

Armadillo-400シリーズでは、ユーザーランドの標準ルートファイルシステムとして、Atmark Distと呼ばれるソースコードベースの開発ディストリビューションから作成したinitrd[34]イメージを使用します。

[注記]ルートファイルシステムとは

ファイルとディレクトリの階層的な構造をファイルシステムといいます。

Windowsも階層的なファイル構造を持っていますが、Linuxシステムとは決定的な違いがあります。それは、Linuxシステムのファイルシステムにはドライブという考え方がないことです。

Windowsでは複数のストレージデバイスがある場合、デバイスごとにドライブという形で区別し、別々の階層構造を持ちます。Linuxシステムでは、複数のデバイスがある場合でも、ルートディレクトリから連なる一つの階層構造として表現します。

ストレージデバイスをファイルシステムと関連付け、システムから使用できるようにすることを、「マウントする」といいます。Linuxシステムでは、任意のディレクトリにデバイスをマウントすることができます。つまり、USBメモリを/mntディレクトリにマウントし、SDカードを/home/atmark/sdcardディレクトリにマウントするといったことができます。デバイスがどれだけ増えようとも、必ずルートディレクトリから辿ることができます。

ルートファイルシステムとは、ルートディレクトリにマウントされたファイルシステムの事です。

ルートファイルシステムには、アプリケーションプログラム、ライブラリ、設定ファイル、データファイルなどが置かれます。本書では、主にユーザーランドで動作するアプリケーションプログラム開発方法についての解説をおこないます。Linuxカーネルのデバイスドライバの開発などは、本書の範囲外になります。

標準ではinitrdイメージはフラッシュメモリのユーザーランドリージョンに配置され、Hermit-AtによってRAMディスクに展開されます。initrdイメージは、Hermit-Atのブートオプションを変更することで、TFTPサーバー上にも配置することができます。

また、ルートファイルシステムは、カーネルパラメータを設定することで、RAMディスク以外にストレージ(microSD/USB)またはNFSサーバー[35]上に配置することもできます。

[注記]標準以外のユーザーランド

Atmark Distで作成した標準ユーザーランドの他に、オプションとしてDebian GNU/Linux 5.0 (コードネーム "lenny")ベースのユーザーランドも提供しています。

Debian GNU/Linuxベースのシステムでは、ソフトウェアパッケージのインストールが一つのコマンドできたり、セルフコンパイル環境を整えることもできます。開発の初期段階や、サーバーとして使用する場合にはDebian GNU/Linuxをユーザーランドとして選択するのも良いでしょう。

5.2. 起動の仕組み

本章では、標準状態のArmadilloに電源を投入してから、ログイン画面が表示されるまでの起動シーケンスを説明します。

ブートローダー、カーネル、ユーザーランドイメージは、フラッシュメモリのそれぞれ対応する領域に書き込まれているものとします。

大まかな起動の流れは、以下のようになります。

  1. ブートローダが起動し、カーネルとユーザランドをRAMに展開する。
  2. ブートローダーを抜けて、カーネルに実行を移す。
  3. カーネルが様々なデバイスの初期化処理をおこなう。
  4. カーネルがユーザーランドのinitというアプリケーションプログラムを実行する。
  5. initが様々な初期化処理を呼び出す。
  6. initがgettyというアプリケーションプログラムを起動する。
  7. gettyがloginというアプリケーションプログラムを起動する。
  8. loginがログイン画面を表示する。

5.2.1. カーネルが動作するまで

Armadilloシリーズは、汎用CPUボードという性格上、ユーザーが書き換え可能なフラッシュメモリを搭載しています。ユーザーが操作を誤ってフラッシュメモリを消去してしまっても復旧が可能なように、Armadilloはジャンパによって、電源投入後の動作(ブートモード)を変更することができます。

Armadillo-400シリーズでは、JP1の設定によってUARTブートモードと、オンボードフラッシュメモリブートモードを選択することができます。

JP1をショート[36]にすると、UARTブートモードとなります。UARTブートモードは、フラッシュメモリのブートローダーが壊れた場合など、システム復旧のために使用します。詳しくは、「Armadillo-400シリーズ ソフトウェアマニュアル」の「ブートローダーを出荷状態に戻す」を参照してください。

JP1をオープン[37]にしておくと、オンボードフラッシュメモリブートとなります。オンボードフラッシュメモリブートモードでは、フラッシュメモリのブートローダー領域に配置されたブートローダーが起動されます。これが、通常運用での設定です。

Hermit-Atブートローダーは起動されると、まず、DRAMの初期化、拡張インターフェースのIOポートを入力にするなどの必要最小限の設定をおこないます。その後の動作は、JP2の設定によって決定されます。JP2をショートにしておくと保守モード、オープンにしておくとオートブートモードとなります。

保守モードの場合、Hermit-Atブートローダーはプロンプトを表示し、コマンド入力待ちとなります。保守モードでは、フラッシュメモリの更新、ブートデバイスやカーネルパラメータの設定などを行うことができます。詳しくは、「Armadillo-400シリーズ ソフトウェアマニュアル」の「付録A Hermit-Atブートローダー」を参照してください。

参考として、図5.1「Hermit-At保守モード時の表示」に保守モード起動時のシリアルコンソールへの表示を示します。このような表示になった場合は、ジャンパピンの設定を確認してください。

Hermit-At v2.0.1 (armadillo4x0) compiled at 21:10:18, Apr 27 2010
hermit>

図5.1 Hermit-At保守モード時の表示


ジャンパの設定による、ブートモードの違いを表5.1「ジャンパ設定」にまとめます。

表5.1 ジャンパ設定

JP1 JP2 ブートモード

オープン

オープン

オンボードフラッシュメモリブート/オートブートモード

オープン

ショート

オンボードフラッシュメモリブート/保守モード

ショート

オープン/ショート

UART ブート


Hermit-Atブートローダーは、まず自分自身をRAMにコピーします。

ブートローダーのコピー

図5.2 ブートローダーのコピー


次にブートデバイス[38]からカーネルイメージとユーザーランドのinitrdイメージを読み込み、RAM上にコピーします。

Armadilloでは、RAMディスクという仕組みを使い、RAMの一部をブロックデバイス[39]として使用します。Atmark Distで作成したinitrdイメージは、RAMディスク上にコピーするとEXT2ファイルシステムとして見えます。Armadilloでは、これをルートファイルシステムとして使用します。

カーネルとユーザーランドをコピー

図5.3 カーネルとユーザーランドをコピー


最後に、カーネルパラメータをRAM上の特定番地に書き込みます。その後、ブートローダーを抜け、カーネルの開始番地へ実行を移します。この一連の処理を、Linuxカーネルをブートすると表現します。

カーネルの起動

図5.4 カーネルの起動


Hermit-AtブートローダーがLinuxカーネルをブートするときの、コンソールへの出力を図5.5「Hermit-Atオートブートモード時の表示」に示します。

Hermit-At v2.0.1 (armadillo4x0) compiled at 21:10:18, Apr 27 2010  1
Uncompressing  kernel.............................................................................
....................................done.  2
Uncompressing ramdisk.............................................................................
..................................................................................................
..................................................................................................
..................................................................................................
.......................................................done.  3
Linux version 2.6.26-at8 (2.6.26) (atmark@atde3) (gcc version 4.3.2 (Debian 4.3.2-1.1) ) #5 PREEMP
T Fri Jul 9 16:50:08 JST 2010  4
:
:
:

図5.5 Hermit-Atオートブートモード時の表示


1

Hermit-Atブートローダーはシリアルの初期化が完了すると自身のバージョンを表示します。

2

カーネルイメージが圧縮されている場合、展開しながらRAM上にコピーします。

3

同様に、ユーザーランドイメージを展開しながらRAM上にコピーします。ユーザーランドイメージのコピーが完了すると、カーネルに実行を移します。

4

この行以降は、カーネルが表示しています。

5.2.2. カーネルの初期化処理

ブートローダーから実行を移されると、ようやくLinuxカーネルが動作を開始します。

Armadilloのカーネル起動ログの例として、Armadillo-420の起動ログを図5.6「Armadillo-420カーネルブートログ」に示します。

Linux version 2.6.26-at8 (2.6.26) (atmark@atde3) (gcc version 4.3.2 (Debian 4.3.2-1.1) ) #5 PREEMP
T Fri Jul 9 16:50:08 JST 2010
CPU: ARM926EJ-S [41069264] revision 4 (ARMv5TEJ), cr=00053177
Machine: Armadillo-420
Memory policy: ECC disabled, Data cache writeback
CPU0: D VIVT write-back cache
CPU0: I cache: 16384 bytes, associativity 4, 32 byte lines, 128 sets
CPU0: D cache: 16384 bytes, associativity 4, 32 byte lines, 128 sets
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 16256  1
Kernel command line: console=ttymxc1,115200  2
MXC IRQ initialized  3
:
各デバイスの初期化処理
:
RAMDISK: ext2 filesystem found at block 0  4
RAMDISK: Loading 13621KiB [1 disk] into ram disk... done.
VFS: Mounted root (ext2 filesystem).  5
Freeing init memory: 132K
init started:  BusyBox v1.00 (2010.06.03-06:57+0000) multi-call binary  6

図5.6 Armadillo-420カーネルブートログ


1

ブートローダーから実行が移ると、カーネルはまず自身のバージョン、CPUアーキテクチャ、マシン名、メモリの状態などを表示します。

2

カーネルパラメータは、「console=ttymxc1,115200」が使用されています。

3

ここから、ボード固有のデバイスの初期化が始まります。

4

RAMディスクのblock0にext2ファイルシステムを検出しました。

5

検出したファイルシステムをルートファイルシステムとしてマウントします。

6

ルートファイルシステムの所定のパスにinitプログラムが見つかると、カーネルはinitを実行します。この行から、initによって表示されています。

5.2.3. ユーザーランドの初期化処理

カーネルの初期化が完了すると、最初のプロセスとしてinitというアプリケーションプログラムが実行されます。initは、まず、コンソールの初期化をおこない、次に/etc/inittabというファイルに書かれた設定に従って、コマンドを実行します。

デフォルトでは、システムコンソールとしてカーネルパラメータのconsoleオプションで指定されたデバイスを使用します。もし、consoleオプションが指定されていない場合は、/dev/consoleを使おうとします。

図5.6「Armadillo-420カーネルブートログ」のように、Hermit-Atブートローダーは、標準でconsoleオプションにttymxc1を指定します。ttymxc1は、Armadillo-400シリーズのシリアルインターフェース1に対応する、シリアルデバイスです[40]。そのため、initは、シリアルインターフェース1をシステムコンソールとして設定します。

次に、initは、/etc/inittabファイルの中身を読み込み、その内容に従って処理を行います。

inittabには、一行ごとにinitが実行すべきコマンドが記述してあります。inittabの書式は、以下のようになっています。

id:runlevel:action:process

図5.7 inittab の書式


idには起動されるプロセスが使用するコンソールを指定します。省略した場合は、システムコンソールが使用されます。

runlevelは、Atmark Distで生成されるユーザーランドに含まれるinitでは、無効です。

actionはどのような状態のときにprocessに指定したコマンドを実行すべきかをあらわします。actionに指定可能な値を表5.2「initのactionに指定可能な値」に示します。

表5.2 initのactionに指定可能な値

いつ process を実行するか

sysinit

システム初期化時。

respawn

sysinit 終了後。このアクションで起動されたプロセスが終了すると、再度 process を実行する。

shutdown

システムをシャットダウンする前。

ctrlaltdel

Ctrl-Alt-Delete キーの組み合わせが入力されたとき。


例として、Armadillo-420のinittabは以下のようになっています。

::sysinit:/etc/init.d/rc

::respawn:/sbin/getty -L 115200 ttymxc1 vt102

::shutdown:/etc/init.d/reboot
::ctrlaltdel:/sbin/reboot

図5.8 Armadillo-420のinittab


図5.8「Armadillo-420のinittab」からわかるように、システム初期化時には/etc/init.d/rcが実行されます。

Armadilloでは、/etc/init.d/rcはシェルスクリプトになっています。シェルスクリプトは、シェルで実行できるコマンドを記述したスクリプトです。詳細は、第2部の「シェルスクリプトプログラミング」で説明します。

Armadillo-420の/etc/init.d/rcは以下の処理を実行します。

  1. 一度ルートファイルシステムをリードオンリーでリマウントし、fsckにより、ルートファイルシステムをチェックします。問題があればリブートします。
  2. ルートファイルシステムをリード/ライト可能でリマウントします。
  3. procfs、usbfs、sysfsをマウントします。[41]
  4. ログ関連のファイルをクリアします。
  5. /etc/issue、/etc/issuet.netファイルの設定をします。[42]
  6. /etc/rc.d/ディレクトリにある、Sから始まるファイル(初期化スクリプト)を順番に実行します。
  7. 赤色LEDが点滅していたら、点滅を停止し赤色LEDを消灯させます。

/etc/rc.dディレクトリ内には、Sからファイル名が始まる、初期化スクリプトがあります。これらの初期化スクリプトで、コンフィグ領域のリストアや、ファイヤーウォールの設定、ネットワークインターフェースの有効化、各サーバーの起動などをおこないます。

また、処理の一番最後に/etc/config/rc.localというファイル名で実行可能なファイルがあるか確認し、ファイルがあればそれを実行します。/etc/config/ディレクトリは、flatfsdでコンフィグ領域に保存可能なディレクトリですので、開発時などに自動起動プログラムを試したいという場合に使用することができます。

sysinitアクションに指定された以上の処理が完了すると、initは次に、respawnアクションに指定されたコマンドを実行します。Armadillo-400シリーズの場合は、gettyというプログラムを起動します。

gettyは、/etc/issueの内容を読み取り、コンソールに表示します。そして、ログインユーザー名の入力待ちになります。ログインユーザー名が入力されると、それを引数として、loginというプログラムを起動します。

loginは、ログイン名を指定されて起動されると、パスワードの入力待ちになります。パスワードが入力されると、/etc/passwd及び/etc/shadowの内容とログインユーザー名、パスワードを照合して、認証をおこないます。ユーザー名とパスワードが一致すると、/etc/passwdで指定されたユーザー用のシェルを起動します。

シェルは、起動されるとプロンプトを表示して、コマンドの入力待ちになります。

5.3. ルートファイルシステムのディレクトリ構成

Linuxシステムでのディレクトリ構成には、デファクトスタンダード(事実上の標準)となっている構成があります。それぞれのディレクトリに何を格納するかということも、慣習的に決まっています。それぞれのディレクトリには特定の役割がありますので、それを理解することで、ファイルを探す場合にどのディレクトリを探せばよいか、また、ファイルを追加する場合にどのディレクトリに置けば適切かということが分かります。

[注記]ディレクトリ構成の標準規格

ディレクトリ構成の標準規格としてFHS(Filesystem Hierarchy Standard : ファイルシステム階層標準)があります。

すべてのLinuxシステムがこの標準に従っているわけではありませんが、特別な理由がない限り、FHSに従ったディレクトリ構成とするのが望ましいでしょう。

Armadillo-400シリーズのルートファイルシステムの主なディレクトリの構成は、以下のようになっています。

表5.3 ディレクトリ構成

ディレクトリ ディレクトリの内容

/

ルートディレクトリ、ルートファイルシステムのマウントポイント

/bin

基本的なユーザーコマンドの実行ファイル

/dev

デバイスファイル

/etc

設定ファイル

/etc/config

フラッシュメモリのコンフィグ領域に保存できるファイル

/etc/default

コンフィグ領域の初期化のためのファイル

/etc/init.d

初期化スクリプト

/etc/rc.d

初期化スクリプトへのシンボリックリンク

/home

ホームディレクトリ

/home/ftp

FTPサーバーのドキュメントルート

/home/guest

guestユーザーのホームディレクトリ

/home/www-data

Webサーバーのドキュメントルート

/lib

基本的なライブラリ

/mnt

一時的にマウントするファイルシステムのマウントポイント

/proc

procfsのマウントポイント(プロセス情報)

/root

rootユーザーのホームディレクトリ

/sbin

基本的なシステム管理用コマンドの実行ファイル

/sys

sysfsのマウントポイント(システム情報)

/tmp

一時的なファイル

/usr

ユーザー共有情報ファイル

/usr/bin

必須でないユーザーコマンドの実行ファイル

/usr/sbin

必須でないシステム管理者用コマンドの実行ファイル

/usr/lib

必須でないライブラリ

/var

頻繁に更新されるファイル

/var/log

ログが保存されるディレクトリ


5.3.1. 実行ファイル

アプリケーションの実行ファイルは、/bin、/usr/bin、/sbin、/usr/sbinディレクトリに置かれます。

これらのディレクトリ内にあるファイルが、シェルでコマンドを入力したときに検索されます。そしてコマンドと同じファイル名のファイルがこれらのディレクトリに合った場合、そのファイルが実行されます。

5.3.2. ホームディレクトリ

ユーザーごとのホームディレクトリは/homeディレクトリに用意されています。

Armadillo-400シリーズでは、ftp、guest、www-dataディレクトリがあります。但し、ftpとwww-dataユーザーでは、ログインすることはできません。また、rootユーザーでログインした場合のホームディレクトリは、/rootディレクトリになります。

/home/ftpと/home/www-dataは、それぞれFTPサーバーとWebサーバーのドキュメントルートになっています。特に、/home/ftp/pubディレクトリは、ftpで書き込み可能なディレクトリです。ramfs[43]でマウントされているので、RAMが許す限りの大きなファイルを書き込むことができます。

5.3.3. ライブラリ

ライブラリファイルは/libまたは/usr/libディレクトリに置かれます。

共有ライブラリを使用するプログラムを実行する場合は、これらのディレクトリ内に共有ライブラリを置いておく必要があります[44]

5.3.4. デバイスファイル

/devディレクトリには、デバイスファイルが置かれます。

デバイスファイルは、デバイスを仮想的にファイルとして表したものです。デバイスファイルに対して操作を実行することにより、デバイスを制御することができます。

例として、/dev/ttymxc1はシリアルインターフェース1のシリアルデバイスをファイルとして表したものです。/dev/ttymxc1に対してデータの読み書きをすることで、シリアルデバイスからデータを受信/送信することができます。

5.3.5. プロセス、システムの状態

/proc、/sysディレクトリ内のファイルを操作することで、プロセス、システムの状態を参照、変更することができます。

/procにはprocfs、/sysにはsysfsがマウントされています。procfs、sysfsはカーネル内部のデータ構造にアクセスすることができる機能を提供する仮想的なファイルシステムです。

5.3.6. ログ

カーネルメッセージやアプリケーションの動作ログなどは/var/logディレクトリに保存します。

5.3.7. 設定ファイル

設定ファイルは、/etcに置かれます。

/etc/configディレクトリ以下のファイルは、flatfsdコマンドを使って、フラッシュメモリのコンフィグ領域に保存することができます。コンフィグ領域の内容は、初期化スクリプトで/etc/configディレクトリにリストアします。

このディレクトリにrc.localという名前で実行可能なファイルを置くと、起動時に初期化スクリプトによって実行されます。



[34] initial RAM disk。一般的なLinuxシステムでは、initrdはHDDなどにあるルートファイルシステムをマウントする前に一時的に使用する「ミニ」ルートファイルシステムとして使用されます。Armadillo-400シリーズでは、initrdをそのままルートファイルシステムとして使用します。

[35] カーネルでNFSサポートを有効にした場合

[36] ジャンパソケットを挿した状態

[37] ジャンパソケットを挿していない状態

[38] 標準設定の場合、フラッシュメモリ。Armadillo-400シリーズではmicroSDも指定可。

[39] HDDなどのブロック単位でアクセスし、ランダムリード/ライトが可能なデバイス。バイト単位でアクセスし、シーケンシャルリード/ライトしかできないデバイスはキャラクタデバイスといいます。

[40] 「Armadillo-400シリーズ ソフトウェアマニュアル」の「UART」参照

[41] これらは、仮想ファイルシステムと呼ばれるもので、カーネル内部の状態がファイル内容に動的に反映されます。

[42] これらは、コンソール(issue)またはネットワーク経由(issue.net)のログイン時に表示される文字を制御します。

[43] RAMの一部を直接使用するファイルシステム

[44] LD_LIBRARY_PATH環境変数を指定することによって、これらのディレクトリ以外に共有ファイルを置くこともできます。