データ収集システムではたくさんのプロセスが同時に様々な作業をします。 そのため、これらのプロセスの間の同期をとることは非常に重要です。また、 これらのプロセスの一つがかけてもデータ収集が出来なくなるという場合もあ ります。また場合によってはソフトウエアの設計の都合により、プロセスの立 ち上げ方や、立ち上げの順序が複雑になっている場合もよくあります。このよ うに複雑に絡み合ったプロセスを円滑に動かして行くためにはそういった複雑 な手順を記憶し、実行する専用の仕組みが必要です。通常はランコントロール と呼ばれるものです。
ランコントロールにはいくつかの側面があります。まずはプロセス管理です。 どのプロセスがどの計算機の上で走るべきかを知っていて、それらを順に起動 していくことやそれらが正しい状態で走っていることを監視することです。走 り出したプロセスは内部的にいくつかの状態を持っているのが普通です。立ち 上げたばかりの初期状態から、必要なパラメータなどを読み込んで次の実験の 設定を待っているスタンバイ状態、実験開始の指示を待っている状態、データ 収集中、データ収集中断中、データ収集を終わって終了処理を行っている状態、 そして再びスタンバイ状態へと移っていきます。これらの状態遷移はオペレー タの操作によって起こるものや、ハードウエア割込によるもの、ソフトウエア の例外によって起こるものなど様々です。これらのトランザクションを検知し、 必要な状態へそれぞれのプロセスを遷移させるのもランコントロールの仕事で す。ランコントロールはその性格からオンラインデータベースやロギングとも 密接な関係があります。場合によってはスローコントロールとよばれる周辺機 器の制御も必要になります。
このようにランコントロールは様々なトランザクションを集中的に受け付け、 実験の状態遷移を正しく司るプロセスです。実験の非常に複雑な手順を理解し ていなければなりません。ある意味ではエキスパートシステムです。オペレー タに次になにをさせるかサジェスチョンも与えることができればより実験は安 定になるでしょう。
こういったシステムの実装を考えてみましょう。状態遷移のトリガーはオペ レータの操作と外部からのメッセージ受信などです。オペレータ操作はキーボー ドキーからのコマンドかもしれないし、こったシステムではXウインドウのパ ネルに並んだボタンやスライダーかもしれません。外部からのものは、他のプ ロセスからのシグナルやメッセージ、セマフォ、ソケット通信などいろいろな ものが考えられます。これらをすべてここではトランザクションと呼ぶことに します。ランコントローラはまず状態を定義します。その状態において受け付 けうるすべてのトランザクションについて、それを受け付けると(1)何をして、 (2)どの状態に移るかがつぎに記述されなければなりません。プログラムの中 に書き込むことも可能ですが、スクリプトに記述されたものを読み込んでその 通りに実行できることが望ましいでしょう。何をするかと言うところではプロ セスの起動やシグナル送信、メッセージ送信、シェルやリモートシェルコマン ドの発行などが出来なければなりません。
ネットワークに分散した環境でさまざまなプロセスに指示を与えるにはその ための通信機構を用意する必要があります。ソケット通信がもっとも自然な方 法でしょう。プロセスを場合によっては殺して再起動する必要もでてきます。 rshコマンドだけではやりにくいこともあるでしょうからそれぞれの計算機に デーモンを走らせ、ランコントローラのパネルからすべての機械に目が行き届 き、操作が可能な環境を作る必要があります。ネットワークシェルといったほ うがいいようなものでしょう。こういったプログラムはまさにこれまで勉強し た様々な手法を総動員して作る必要があります。こういった環境を用意した上 で、それらを組み合わせてランコントローラを作ります。
(演習問題) 1. コントローラとプロセスとの間の通信のための関数を用意する。 ctl_connect( ) コントローラとの接続確立 ctl_disconnect( ) コントローラとの接続終了 ctl_send( char * message ) コントローラへのメッセージ送信 ctl_receive( char * buf, int buflen ) メッセージ受信 ctl_signal( int sig ) コントローラへのシグナル割り込み(ネットワークの 別の機械で動いているときはデーモンが必要) 2. 状態遷移を次のように記述する文法を決めた。サポート関数を用意せよ。 state 状態名; #状態名の宣言 in 状態名 #状態「状態名」での処理記述の開始 end 状態名 #同終了 on トランザクション #トランザクション処理記述の開始 end トランザクション do 処理 #処理としてコマンド実行 tell プロセス名 メッセージ #処理としてプロセスへメッセージ送信 goto 状態 #処理として状態へ遷移 #トランザクション message メッセージ from プロセス #メッセージ受信 command コマンド #オペレータ signal シグナル #シグナル受信 サポート関数は ctl_open( char * statedescriptorfilename ) 上述のファイルを開く ctl_go( ) 処理モードに突入 3. ネットワーク分散シェルを設計する。それぞれの計算機で走っているデーモンを介し て次のような作業が行なえる関数を用意する。 nsh_open( char * host ) ホストとの接続確立 nsh_exec( char * image, int argc, char ** argv ) プロセスの起動 nsh_kill( int pid ) 相手ホスト上のプロセスへのシグナル送信 nsh_attach() 相手ホストシェル起動、標準入出力を確保 nsh_detach( ) シェルとの接続中断 nsh_cdir( char * dir ) 相手計算機でのディレクトリーの移動 nsh_close( ) ホストとの接続閉鎖