簡易データ収集系の例題

本デバイスドライバの機能を使って、 簡単なデータ収集システムのサンプルを作ってみました。 構成としては、以下の三つのプロセスが連係して動作します。

commander
標準入力からコマンド文字列を読んで、 データ収集の制御 (start/stop/reset) や ファイル名の指定/クローズ処理の指示を行ないます。
recorder
バッファされたイベントデータを /dev/dc から読み込み、 ファイルに書いたり analyzer に渡したりします。 analyzer の処理が遅くデータ収集に追い付かない時は、 イベント単位で間引きを行ないます。
analyzer
オンライン解析プロセスです。 analyzer 本体が面倒を見るのは、 各イベントのデータをユーザールーチンに渡す所までです。 ユーザールーチンは使用者が用意しリンクするわけですが、 処理内容 (ヒストグラミング、ディスプレイ方法等) は全く自由です。 ただし、以下の三つのエントリーが必要です。
void hstdef_()
analyzer 起動時に一度だけ呼ばれます。 各種初期設定やヒストグラムの定義を行ないます。
void hstend_()
analyzer 終了時に一度だけ呼ばれます。 各種後処理やヒストグラム領域の解放を行ないます。
void event1_(unsigned short data[])
各イベント毎に呼ばれます。 ヒストグラムのカウントアップを行ないます。
末尾にアンダースコア "_" が付いているのは、 Fortran でユーザールーチンを記述する便宜を考慮したものです。 Fortran で書く場合には、各々
  SUBROUTINE HSTDEF
  SUBROUTINE HSTEND
  SUBROUTINE EVENT1(DATA)
  INTEGER*2 DATA(*)
がエントリーとなります。 HBOOK と PAW を使った例題 として "event1.f" を付けましたので参考にしてください。
各プロセス間のデータ交換は共有メモリを介して行なっており、 データの構成やキー等の情報は "crashm.h" に記述されています。 また、analyzer/recorder 間のデータ待ち/解除の制御はセマフォを 使っています。 いずれも常識的な方法ですが、詳しく知りたい人は SystemV IPC (Inter-Process Communication) に 関する参考書を読んでください。 上記のソースは、いずれも 1〜2 ページの極短いものなので、 この手の「お勉強」をしたい人にも適当ぢゃないかと思います。

所謂オフライン解析のためのプログラムも用意しました。

player
一旦ファイルに落したイベントデータを読み込んで解析を行ないます。 制御は commander と互換のコマンド文字列を標準入力から 読み込んで行なわれます。 イベント処理は analyzer と同じユーザールーチンをリンクして 実行します。 CAMAC デバイスドライバをインストールしていないシステムでも、 同じインターフェースを利用できるメリットが有ります。
オンラインではイベント処理の「非同期実行」のため、 commander, recorder, analyzer にプロセスを分けましたが、 オフラインでは同期実行なので一つにまとめています。 ただし解析中もキー入力を受け付けるようにするため、 fork によるプロセスの二重化、および signal と pipe によるプロセス間通信を 使っています (これらは IPC 以前から有るマルチプロセス制御です)。

サンプルシステムの実行形式の make は

      % make DAQ
で行なわれます。 ただし、 CERN library がシステムにインストールされている事を仮定しています。 また、"event1.f" は Fortran で書かれていますが、 g77 がインストールされている事を仮定しています。 メインが C で書かれている時の Fortran ライブラリをリンクする方法は チョット有用かも知れません。Makefile を覗いてみてください。

さて、 commander は最低限の機能しか持っていないので、 とても使い易いとは言えません (VMS/DCL 風のコマンドの省略ぐらいはサポートしていますが)。 そこで、Tcl/Tk による GUI の「皮」を被せて使い易さの向上を図ったのが "rei" というスクリプトです。

Tcl/Tk とはスクリプト言語 (インタープリタ) で、 マウス操作による GUI な制御を短いステップで書く事ができ、 速度の要求されない処理 (大抵の対話型処理はそうですが) の部分を 手っ取り早く記述するには便利です。 Tcl/Tk に関する参考書も今では巷に溢れているので、 詳しい事を知りたい方は適当に探してください。 "rei" はバージョン 4.0 以降 (確認されているのは 8.0.5 まで) の Tk で動作します。 ちなみに "rei" というのは例題の rei ではなく、 火川神社の巫女さんの名前のつもりで付けました (もう古い?)。

"rei" を起動すると、 commander, recorder, analyzer がサブプロセスとして 自動的に立ち上げられます。 "rei" の起動は、PATH 指定でも alias でもシンボリックリンクでも構いません。 ただし、commander, recorder, analyzer は "rei" と同じディレクトリに なければなりません。 また、起動時に

      % rei offline
のように引数を与えれば、player が起動されます。

"rei" の実行画面は以下のようなものです。 使える機能は全てボタンに割り当てられていますので、 説明が無くても使い方はわかると期待します。 誤操作を防ぐために、 システムの状態 (データ収集中、ファイル書き込み中) に応じて 危険なボタンはグレーアウト (使用禁止) されます。 ボタンをマウスクリックする代わりに、 下線の引かれた文字と ALT キーを同時に押しても 同様の動作をします。

一秒毎に表示が更新される統計情報は以下の意味を持っています。

Interrupt
CAMAC の LAM によって発生した割り込みの回数です。
Lost
バッファが溢れて採り込めなかったイベントの個数です。
Recorded
recorder が /dev/dc1 から読み出したイベントの個数です。 一回の Start/Stop サイクルでは Interrupt - Lost になると 期待されます。
Analyzed
analyzer が解析したイベントの個数です。
Error
イベント長とデリミタの非整合性から、 データが壊れていると判断されたイベントの個数です。 これらは analyzer には渡されません。
表示画面下部の Scaler では、 CAMAC スケーラの値を一秒毎に読み出して表示しています。 スケーラのステーションナンバーと読み出すチャネル数は、 各々 N と CH で設定します (数字または nil と表示された部分をマウスクリックしてください)。 表示されたデータは Write ボタンによって (イベントデータとは別の) ファイルに書き出す事ができます。

スケーラ情報をイベントデータと同等に扱うのは難があるので (もちろん“スケーライベント”をハード的に作れば別ですが)、 システムの無垢な性格 (?) を残すために、 デバイスドライバまで巻き込んで スケーラの扱いを支援する事は止めました。 が、実際上は不便な事も多かろうと思いまして、 このような形の支援を付け加えた次第です。

デフォルトではスケーラ情報の更新間隔は一秒となっていますが、起動時に

      % rei 2000
という形式でミリ秒単位の指定が可能です。

さて、 "rei" を eXit によって正常終了すると、 commander, recorder, analyzer のサブプロセスは自動的に消去され、 共有メモリおよびセマフォも削除されます。 しかし何らかの理由で異常終了した場合には、 サブプロセスが残っているため "rei" を再起動できなくなりますので、 ps によってプロセス状態を確認し、kill してください。 あるいは安直に

      % killall commander recorder analyzer
としても良いと思います (これらを二つ以上起動していると、 そもそもマトモに動きませんから)。 特にデータ収集の最中に異常終了した場合は 割り込みが発生し続けてしまいますから、 再起動により初期化を行なうのは重要です。 一方、共有メモリやセマフォは残っていても ("rei" を使い続ける限り) 特に害はありませんが、 状態の確認 (ipcs) や削除 (ipcrm) をしたい場合には、 こちらの方法を参照してください。

戻る