VxWorks

ホストとVxWorksとの通信機能が“vxworks/vxweus.l”ファイルで提供されている。 VxWorks上にvxwservサーバを常駐させることにより、 ホスト上のEusLispからvxwservに コネクションを張り、vxwsプロトコルに従った コマンドを送ることにより、VxWorksの関数を起動し、引数を送り、 結果を受け取ることができる。

VxWorksのソフトはSunのcコンパイラによって開発することができる上、 データ表現がsun3, sun4, VME147の間で共通であることを利用して、 vxwsプロトコルは、バイナリモードで動作することができる。

VxWorks側の起動

VxWorksにログインし、“*eusdir*/vxworks/vxwserv.o”をロードする。 その後、vxwservタスクをspawnする。 vxwservはVxWorks上の2200番ポートをlistenする。 2200が塞がっている場合、2201, 2202, ...を試す。 正しくbindされたポート番号が表示される。

% rlogin asvx0  (あるいはetlic2上であれば、% tip asvx[01] も可能)
-> cd "atom:/usr/share/src/eus/vxworks"
-> ld <vxwserv.o
-> sp vxwserv
port 2200 is bound.

VxWorksのiコマンドで、vxwservタスクが常駐したことを確かめる。 同じ要領で、eusから呼び出したいVxWorksのプログラムをVxWorks上にロードする。 その後、EuslispとVxWorksとの コネクションが張られると、vxwservを走らせたTTYに、次のようなメッセージが 出力される。

CLIENT accepted: sock=9 port = 1129: family = 2: addr = c01fcc10:
VxWserv started with 16394 byte buffer

ホスト側の起動

任意のマシンの上でeusを起動し、“vxworks/vxweus”をロードする。 connect-vxw関数を用いてvxwservに接続する。 接続後、ソケットストリームがvxw-stream*にバインドされる。 以下に、コネクトの例を示す。この例では、VxWorks上のsin, vadd関数を euslispの関数VSIN,VADとして定義している。

(load "vxworks/vxweus")
(setq s (connect-vxw :host "asvx0" :port 2200 :buffer-size 1024))
(defvxw VSIN "_sin" (theta) :float)
(defvxw VAD "_vadd" (v1 v2) (float-vector 3))

VxWorks上に作成される関数が、vxwsを通じて呼び出されるためには、 次の条件を満たさなければならない。

  1. 引数は、32個以内であること、引数に受け取るベクタの容量の合計が connect-vxwの:buffer-sizeで指定した値を越えないこと
  2. structを引数にしないこと、必ずstructへのポインタを引数にすること
  3. 結果は、int, float, doubleまたは、それらの配列のアドレスであること
  4. 配列のアドレスを結果とする場合、その配列の実体は、 関数の外部に取られていること
connect-vxw = `[関数]
&key = (host “asvx0”) (port 2200) (buffer-size 16384) (priority 1280) (option #x1c)

:hostに対してvxwsプロトコルによる通信のためのソケットストリームを作成し、そのストリームを返す。 :hostには、ネットワークにおけるVxWorksのアクセス番号あるいはアクセス名を指定する。 :portには、VxWorks上のvxwservがバインドしたポートを捜すための最初のポート番号を指定する。 このポート番号から、増加方向に接続を試行する。 :optionのコードについては、VxWorksの、spawn関数を参照のこと。 コネクションは、同時に複数張ってよい。

vxw vxw-stream entry result-type args

は、vxw-streamに接続されているVxWorksの関数entryを呼び出し、 その関数に引き数argsを与えてresult-typeで指定された結果を得る。 vxw-streamには、connect-vxwで作成したソケットストリームを与える。 entryには、VxWorksの関数名をストリングで指定するか、あるいは関数の アドレスを整数で指定する。 関数のアドレスを知るには、VxWorksのfindsymbolを呼び出す。 知りたいシンボルは、通常、“_”で始まることに注意。 entryがストリングの場合、VxWorks上でシンボルテーブルの逐次探索が行われる。 result-typeには、結果のデータ型(:integerまたは:float)、 あるいはデータを受け取るベクタ型を指定する。 ベクタは、float-vector, integer-vector, stringのインスタンスである。 general vector(lispの任意のオブジェクトを要素とするベクタ)は指定できない。 結果型は、必ず、実際のVxWorks関数の結果型と一致しなければならない。 argsには、entryに与える引き数を指定する。 引数に許されるEusLispデータは、integer, float, string, integer-vector, float-vector, integer-matrix, float-matrixである。 ポインタを含んだ一般のオブジェクト、一般のベクトルは送れない。 また、送られたベクトルデータは、一旦vxwservが獲得したバッファの中に蓄積される。 例えば、VxWorksに定義された関数“sin”を呼び出すためには、次のように実行すればよい。 (vxw *vxw-stream* “sin” :float 1.0)

defvxw eus-func-name entry args &optional (result-type :integer)

は、findsymbolを用いてvxwを呼び出して、VxWorksの関数の高速な呼び出しを 実現するためのマクロである。 VxWorksの関数entryを呼び出すためのEuslispの関数eus-func-nameを定義する。 このマクロを実行後は、eus-func-nameを呼び出すことにより、VxWorksの関数を呼び出すことができる。 このとき、呼び出しに使用されるソケットストリームはvxw-stream*に固定されている。 ただし、VxWorks側で、関数をコンパイルし直して再ロードした場合、 新しい関数定義が呼ばれるようにするためには、eus側で、defvxwをもう一度 実行し直して、最新のエントリアドレスが指定されるようにする必要がある。