﻿
		IPRPC - Inter Process Remote Procedure Call


							　　2013.01.08   V.0.5.0
							　　2013.01.14   V.0.6.0
							　　2013.01.19   V.0.8.0
							　　2013.01.22   V.0.8.1
							　　2013.02.07   V.0.8.2
							　　2013.02.08   V.0.8.3
							　　2013.03.08   V.0.8.4
							　　2013.03.13   V.0.8.5
							　　2013.04.20   V.0.8.6

■　INTRODUCTION
　このライブラリは同一のコンピュータ内のプロセス間でRPCを実現するためのものである。
このライブラリは以下のモデルでRPCのプログラミングを行う。

__________　　__________　　__________　　__________　　__________　　__________
|　　　　|--->|　　　　|　　|　　　　|　　|　　　　|　　|　　　　|　　|　　　　|
|　　　　|　　|　　　　|--->|　　　　|　　|　　　　|　　|　　　　|　　|　　　　|
|　　　　|　　|　　　　|　　|　　　　|--->|　　　　|　　|　　　　|　　|　　　　|
|　　　　|　　|　　　　|　　|　　　　|　　|　　　　|--->|　　　　|　　|　　　　|
|　　　　|　　|　　　　|　　|　　　　|　　|　　　　|　　|　　　　|--->|　　　　|
|呼出関数|　　|ラッパー|　　|STUB LIB|　　|SKELTON |　　|ラッパー|　　|実行関数|
|　　　　|　　|　　　　|　　|　　　　|　　|   LIB  |　　|　　　　|<---|　　　　|
|　　　　|　　|　　　　|　　|　　　　|　　|　　　　|<---|　　　　|　　|　　　　|
|　　　　|　　|　　　　|　　|　　　　|<---|　　　　|　　|　　　　|　　|　　　　|
|　　　　|　　|　　　　|<---|　　　　|　　|　　　　|　　|　　　　|　　|　　　　|
|　　　　|<---|　　　　|　　|　　　　|　　|　　　　|　　|　　　　|　　|　　　　|
~~~~~~~~~~　　~~~~~~~~~~　　~~~~~~~~~~　　~~~~~~~~~~　　~~~~~~~~~~　　~~~~~~~~~~

　STUB LIBとSKELTON LIBの間はプロセス間通信(IPC)を使って実現されており、このライ
ブラリでは共有メモリと、Mutex/Condを使ったメッセージキューにより実装されている。
その他は通常の関数コールで実現される。
　呼出関数、実行関数と、STUB側およびSKELTON側のラッパー関数は利用者が作成する必要
があるが、STUB LIBとSKELTON LIBはライブラリが提供する。

　このライブラリではRPCの機能のうち
　　１：同期型のRPCと非同期型のRPC
　　２：タイムアウト
　　３：実行のキャンセル
　　４：Multicast型のRPC
をサポートしている。
　非同期型のRPCとは実行関数の実行依頼をすると一旦呼び出し側に制御が戻り、実行関数
の動作が完了すると呼び出し側へはコールバック関数により結果が通知される仕組みであ
る。これにより呼び出し元は呼び出し先の動作の完了を待つことなく次の動作を実行する
ことができる。
　タイムアウトは呼び出し時に実行関数のタイムアウト時間を設定し、タイムアウトが発
生すると、エラーとして呼び出し元に制御が戻る仕組みである。実行関数内でタイムアウト
機能が実装されていなくても、STUB LIBないでタイムアウト機能が組み込まれているため、
タイムアウトが発生した場合は呼び出し元に制御が戻るようになっている。その場合、
STUB LIBでタイムアウトが発生した後、実行関数からリターンがあっても結果は捨てられ
るので注意する。
　実行のキャンセル機能は、一旦呼び出し元から呼び出し先の実行関数がコールされた後、
呼び出し元から実行されている動作をキャンセルするためのものである。キャンセル機能
はライブラリにキャンセル実行の動作を伝えるのみで、実際に動作のキャンセルができる
かどうかは実行関数の実装による。従って、キャンセル呼び出しの関数が成功で返ってき
ても本当に動作がキャンセルできるかは実装依存となる。
　Multicast RPCは1度の関数呼び出しで複数の相手に実行制御を渡すことができる。例え
ば呼び出し側はFUNC-Aという関数の呼び出しに対し、PROCESS BのFUNC-B、PROCESS Cの
FUNC-C、PROCESS DのFUNC-Dが実行されるようなケースである(下記図）。この場合SKELTON
側（実際に関数を実行する側）は通常のRPCと同一の動作となるが、STUB側（関数を呼び出
す側）は戻り値が通常はそれぞれ呼び出し先の実行関数から返ってくるため複数となる。
従って、戻り値の配列として結果が返ってくる。また、タイムアウトが発生した場合もエ
ラーとせずタイムアウト時間までに返ってきた戻り値は結果として返すようにしている。
　ここで注意してほしいのは、このライブラリでは通常のRPCにおいても呼び出し元と呼び
出し先が同一のプロセスであっても正しく動作する、ということである。従って、
MULTICAST RPCにおいても、呼び出し先のプロセスが呼び出し元のプロセスと同一であって
も動作するので、同一プロセス内でのMULTICAST関数呼び出しにも使える、ということであ
る。

　　　　　　　　　　　　　　　　　　　　　__________　　__________　　__________
　　　　　　　　　　　　　　　　　　　　　|　　　　|　　|　　　　|　　|　　　　|
　　　　　　　　　　　　　　　　　　　　　|　　　　|　　|　　　　|　　|　　　　|
　　　　　　　　　　　　　　　　　　　 |->|SKELTON |--->|ラッパー|--->|実行関数|
　　　　　　　　　　　　　　　　　　　 |　|   LIB  |　　|　　　　|　　|A 　　　|
　　　　　　　　　　　　　　　　　　　 |　|　　　　|　　|　　　　|　　|　　　　|
　　　　　　　　　　　　　　　　　　　 |　~~~~~~~~~~　　~~~~~~~~~~　　~~~~~~~~~~
__________　　__________　　__________ |　__________　　__________　　__________
|　　　　|　　|　　　　|　　|　　　　| |　|　　　　|　　|　　　　|　　|　　　　|
|　　　　|　　|　　　　|　　|　　　　| |　|　　　　|　　|　　　　|　　|　　　　|
|呼出関数|--->|ラッパー|--->|STUB LIB|--->|SKELTON |--->|ラッパー|--->|実行関数|
|　　　　|　　|　　　　|　　|　　　　| |　|   LIB  |　　|　　　　|　　|B 　　　|
|　　　　|　　|　　　　|　　|　　　　| |　|　　　　|　　|　　　　|　　|　　　　|
~~~~~~~~~~　　~~~~~~~~~~　　~~~~~~~~~~ |　~~~~~~~~~~　　~~~~~~~~~~　　~~~~~~~~~~
　　　　　　　　　　　　　　　　　　　 |　__________　　__________　　__________
　　　　　　　　　　　　　　　　　　　 |　|　　　　|　　|　　　　|　　|　　　　|
　　　　　　　　　　　　　　　　　　　 |　|　　　　|　　|　　　　|　　|　　　　|
　　　　　　　　　　　　　　　　　　　 |->|SKELTON |--->|ラッパー|--->|実行関数|
　　　　　　　　　　　　　　　　　　　　　|   LIB  |　　|　　　　|　　|C　　　|
　　　　　　　　　　　　　　　　　　　　　|　　　　|　　|　　　　|　　|　　　　|
　　　　　　　　　　　　　　　　　　　　　~~~~~~~~~~　　~~~~~~~~~~　　~~~~~~~~~~

　また、MULTICASTで呼び出した先の手続きの中でさらにMULTICAST RPCを呼び出すことも
可能である。但し、戻り値の処理がかなり複雑になるのでMULTICAST RPCの先でさらに
MULTICAST RPCを実行することはやらない方がよいであろう。



　このライブラリではIPCの追加の機能としてランデブを実装している。ランデブはスレッ
ド間で同期をとるためのものである。例えば以下のようにランデブポイントに対して、ス
レッドAがスレッドBにメッセージXを送信し、スレッドBがスレッドAに対してメッセージY
を送信するような場合、スレッドAがRendezvSendを呼び出しても、スレッドBが
RendezvRecvとRendezvReplyを呼び出さないと次の動作に進まない。またスレッドBも
RendezvRecvを呼び出さしても、スレッドAがRendezvSendを呼び出さないと次の動作に進
まない。すなわち、スレッド間で実行の同期が起こる。

　　　スレッドA 　　　　　　　　　　　　　　　　　スレッドB 　　　
　　　　　| 　　　　　　　　　　　　　　　　　　　　　 |　　　　　
　　　　　| 　　　　　　　ランデブポイント　　　　　　 |　　　　　
　　　　　| 　　　　　　　　__________　　　　　　　　 |　　　　　
　　　　　| 　RendezvSend 　|　　　　|　　　　　　　　 |　　　　　
　　　　　|---------------->|　　　　|　　　　　　　　 |　　　　　
　　　　　| 　　SEND X　　　|　　　　|　RendezvRecv 　 |　　　　　
　　　　　| 　　　　　　　　|　　　　|<----------------|　　　　　
　　　　　| 　　　　　　　　|　　　　|　　　Return　　 |　　　　　
　　　　　| 　　　　　　　　|　　　　|---------------->|　　　　　
　　　　　| 　　　　　　　　|　　　　|　　RECV X　　　 |　　　　　
　　　　　| 　　　　　　　　|　　　　|　　　　　　　　 |　　　　　
　　　　　| 　　　　　　　　|　　　　|　RendezvReply　 |　　　　　
　　　　　| 　　　　　　　　|　　　　|<----------------|　　　　　
　　　　　| 　　　　　　　　|　　　　|　　SEND Y　　　 |　　　　　
　　　　　| 　　　　　　　　|　　　　|　　　　　　　　 |　　　　　
　　　　　| 　　　Return　　|　　　　|---------------->|　　　　　
　　　　　|<----------------|　　　　|　　　　Return　 |　　　　　
　　　　　| 　　RECV Y　　　|　　　　|　　　　　　　　 |　　　　　
　　　　　| 　　　　　　　　~~~~~~~~~~　　　　　　　　 |　　　　　
　　　　　| 　　　　　　　　　　　　　　　　　　　　　 |　　　　　
　　　　　| 　　　　　　　　　　　　　　　　　　　　　 |　　　　　



■　BUILD THE LIBRARY

　このライブラリを生成するには以下の手順で行う。

　　　$ ./configure prefix=/usr/local USE_HASH=YES OS_TYPE=LINUX
　　　　　　...
　　　$ make

　この時点で上記コマンドを実行したディレクトリにライブラリが生成される。ライブラ
リはstaticなものとsharedなもの両方が生成される。コンフィグレーションのためのパラ
メタの詳細はINSTALLファイルを参照すること。
　この後、インストールのために以下のコマンドを実行する。

　　　$ make install

　これで、configureコマンドで指定したディレクトリ（指定しなかった場合は通常/usr/
local/下）にライブラリがインストールされる。但し、installは一旦rootになって実行
した方がよいかもしれない。



■　GETTING STARTED

　１：テストプログラム実行
　ライブラリ作成後、以下のコマンドを実行することによってテストプログラムがコンパ
イルされる。

　　　$ make test

その結果、ipcTest.outが生成される。このプログラムは以下のように４つのプロセスを
生成してプロセス間でRPCを実行する（IPRPC）。


　　　　　　　　　　　　　　　　__________________
　　　　　　　　　　　　　　　　|　　　　　　　　|
　　　　　　　　　　　　　　　　|　MAIN PROCESS　| PROCESS A, B, C, Dを生成
　　　　　　　　　　　　　　　　|　　　　　　　　|
　　　　　　　　　　　　　　　　~~~~~~~~~~~~~~~~~~
　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　
　　　　　　　　　　---------------------
　　____________　　| 　____________　　| 　____________　　　　____________
　　|　　　　　|　　| 　|　　　　　|　　| 　|　　　　　|　　　　|　　　　　|
　　|　　　　　|　　| 　|　　　　　|　　--->|　　　　　|　　　　|　　　　　|
　　|　　　　　|　　| 　|　　　　　|　　　　|　　　　　|　　　　|　　　　　|
　　|PROCESS A |----- 　|PROCESS B |------->|PROCESS C |------->|PROCESS D |---
　　|　　　　　|　　　　|　　　　　|　　　　|　　　　　|　　　　|　　　　　|　|
　　|　　　　　|　　--->|　　　　　|　　　　|　　　　　|　　　　|　　　　　|　|
　　|　　　　　|　　| 　|　　　　　|　　　　|　　　　　|　　　　|　　　　　|　|
　　~~~~~~~~~~~~　　| 　~~~~~~~~~~~~　　　　~~~~~~~~~~~~　　　　~~~~~~~~~~~~　|
　　　　　　　　　　|----------------------------------------------------------


プロセスAは最初の呼び出しの起点となるプロセスであり、従ってSTUBの機能しか持たな
い。プロセスB、プロセスC、プロセスDは巡回してIPRPCを呼び出す。最終的には巡回は止
まって逆のルートで結果を戻す。
　このプログラムを起動するには以下のにコマンドを入力する

　　　$ ./ipcTest.out 1 0 0

　このコマンドは３つに引数を持ち、最初の引数がマスタープロセスかどうかを示すフラ
グ、2番目がSTUBを使用するかどうかのフラグ、3番目がSKELTONを使用するかどうかのフラ
グである。なおこのコマンドを実行すると４つのプロセスが生成されるが、それぞれ生成
されたプロセスはこのコマンドと同じ実行ファイル、すなわち"./ipcTest.out"を実行する
ようになっている。

　実際にこのコマンドを実行すると以下のようなログが出力される。

./ipcTest.out PID:0xff4; masterProcess:1; useSkelton:0; useStub:0;
　　　　　　　→　MAIN PROCESS
CREATED PROCESS PID:0xff5; AND NOW REGISTER SKELTON MAIN FUNCTION FUNCID:0xfff2001; FUNC:0x804af41; ... ...DONE
CREATED PROCESS PID:0xff6; AND NOW REGISTER SKELTON MAIN FUNCTION FUNCID:0xfff1001; FUNC:0x80494a0; ... ...DONE
CREATED PROCESS PID:0xff7; AND NOW REGISTER SKELTON MAIN FUNCTION FUNCID:0xfff1002; FUNC:0x8049583; ... ...DONE
CREATED PROCESS PID:0xff8; AND NOW REGISTER SKELTON MAIN FUNCTION FUNCID:0xfff1003; FUNC:0x8049666; ... ...DONE
MAIN  :DEBUG1:NOW WAIT CHILD PROCESS TO EXIT PID:0xff4;
MAIN  :DEBUG1:NOW EXEC TEST PROGRAM PID:0xff5; --- CHILD --- ARG1:0; ARG2:0; ARG3:1;
MAIN  :DEBUG1:NOW EXEC TEST PROGRAM PID:0xff7; --- CHILD --- ARG1:0; ARG2:1; ARG3:1;
MAIN  :DEBUG1:NOW EXEC TEST PROGRAM PID:0xff8; --- CHILD --- ARG1:0; ARG2:1; ARG3:1;
./ipcTest.out PID:0xff8; masterProcess:0; useSkelton:1; useStub:1;
　　　　　　　→　PROCESS D
MAIN  :DEBUG1:NOW EXEC TEST PROGRAM PID:0xff6; --- CHILD --- ARG1:0; ARG2:1; ARG3:1;
./ipcTest.out PID:0xff6; masterProcess:0; useSkelton:1; useStub:1;
　　　　　　　→　PROCESS B
./ipcTest.out PID:0xff7; masterProcess:0; useSkelton:1; useStub:1;
　　　　　　　→　PROCESS C
./ipcTest.out PID:0xff5; masterProcess:0; useSkelton:0; useStub:1;
　　　　　　　→　PROCESS A
MAIN  :DEBUG1:NOW CALL SkeltonTest PID:0xff6; SkeltonFunc:0x80494a0; 
SKLTN :DEBUG1:IN SkeltonTest1 PID:0xff6; 
　　　　　　　→　PROCESS Bの起動
MAIN  :DEBUG1:NOW CALL SkeltonTest PID:0xff8; SkeltonFunc:0x8049666; 
SKLTN :DEBUG1:IN SkeltonTest3 PID:0xff8;
　　　　　　　→　PROCESS Dの起動
MAIN  :DEBUG1:NOW CALL SkeltonTest PID:0xff5; SkeltonFunc:0x804af41; 
STUB  :DEBUG1:IN StubTestA PID:0xff5;
　　　　　　　→　PROCESS Aの起動
MAIN  :DEBUG1:NOW CALL SkeltonTest PID:0xff7; SkeltonFunc:0x8049583; 
SKLTN :DEBUG1:IN SkeltonTest2 PID:0xff7;
　　　　　　　→　PROCESS Cの起動
STUB  :DEBUG1:IN FunctioncStubA PID:0xff5;, count:6; fromProcess:StubTest1; toProcess:SkeltonTest2;
STUB  :DEBUG1:IN IPC_CallStubSync PID:0xff5; funcID:0xfff0002; inData:0xb82080b8; inSize:96; outData:0xbfb65254; outSize:0xbfb65258; timeOut:10000;
　　　　　　　→　PROCESS AによるSTUBの呼び出し
SKLTN :DEBUG1:IN skeltonFuncB PID:0xff5; seqNum:0x1; inData:0xb82080b8; inSize:0x60, outData:0xb4f552fc; outSize:0xb4f55300; timeOut:10000;
SKLTN :DEBUG1:IN FunctionB PID:0xff7; count:6; fromProcess:StubTest1; toProcess:SkeltonTest2;
　　　　　　　→　PROCESS Cによる実行関数の呼び出し
SKLTN :DEBUG1: NOW CALL FunctionStubB count:5; from:SkeltonTest2; to:SkeltonTest3;
STUB  :DEBUG1:IN FunctioncStubB PID:0xff7;, count:5; fromProcess:SkeltonTest2; toProcess:SkeltonTest3;
STUB  :DEBUG1:IN IPC_CallStubSync PID:0xff7; funcID:0xfff0003; inData:0xb82080b8; inSize:96; outData:0xb4f4e964; outSize:0xb4f4e968; timeOut:10000;
　　　　　　　→　PROCESS CによるSTUBの呼び出し
SKLTN :DEBUG1:IN skeltonFuncC PID:0xff7; seqNum:0x1; inData:0xb82080b8; inSize:0x60, outData:0xb4eea2fc; outSize:0xb4eea300; timeOut:10000;
SKLTN :DEBUG1:IN FunctionC PID:0xff8; count:5; fromProcess:SkeltonTest2; toProcess:SkeltonTest3;
　　　　　　　→　PROCESS Dによる実行関数の呼び出し
SKLTN :DEBUG1: NOW CALL FunctionStubC count:4; from:SkeltonTest3; to:SkeltonTest1;
STUB  :DEBUG1:IN FunctioncStubC PID:0xff8;, count:4; fromProcess:SkeltonTest3; toProcess:SkeltonTest1;
STUB  :DEBUG1:IN IPC_CallStubSync PID:0xff8; funcID:0xfff0001; inData:0xb82080b8; inSize:96; outData:0xb4ee3964; outSize:0xb4ee3968; timeOut:10000;
　　　　　　　→　PROCESS DによるSTUBの呼び出し
SKLTN :DEBUG1:IN skeltonFuncA PID:0xff8; seqNum:0x1; inData:0xb82080b8; inSize:0x60, outData:0xb4f1d2fc; outSize:0xb4f1d300; timeOut:10000;
SKLTN :DEBUG1:IN FunctionA PID:0xff6; count:4; fromProcess:SkeltonTest3; toProcess:SkeltonTest1;
　　　　　　　→　PROCESS Bによる実行関数の呼び出し
SKLTN :DEBUG1: NOW CALL FunctionStubA count:3; from:SkeltonTest1; to:SkeltonTest2;
STUB  :DEBUG1:IN FunctioncStubA PID:0xff6;, count:3; fromProcess:SkeltonTest1; toProcess:SkeltonTest2;
STUB  :DEBUG1:IN IPC_CallStubSync PID:0xff6; funcID:0xfff0002; inData:0xb82080b8; inSize:96; outData:0xb4f16964; outSize:0xb4f16968; timeOut:10000;
　　　　　　　→　PROCESS BによるSTUBの呼び出し
SKLTN :DEBUG1:IN skeltonFuncB PID:0xff6; seqNum:0x1; inData:0xb82080b8; inSize:0x60, outData:0xb57562fc; outSize:0xb5756300; timeOut:10000;
SKLTN :DEBUG1:IN FunctionB PID:0xff7; count:3; fromProcess:SkeltonTest1; toProcess:SkeltonTest2;
　　　　　　　→　PROCESS Cによる実行関数の呼び出し
SKLTN :DEBUG1: NOW CALL FunctionStubB count:2; from:SkeltonTest2; to:SkeltonTest3;
STUB  :DEBUG1:IN FunctioncStubB PID:0xff7;, count:2; fromProcess:SkeltonTest2; toProcess:SkeltonTest3;
STUB  :DEBUG1:IN IPC_CallStubSync PID:0xff7; funcID:0xfff0003; inData:0xb82080b8; inSize:96; outData:0xb574f964; outSize:0xb574f968; timeOut:10000;
　　　　　　　→　PROCESS CによるSTUBの呼び出し
SKLTN :DEBUG1:IN skeltonFuncC PID:0xff7; seqNum:0x2; inData:0xb82080b8; inSize:0x60, outData:0xb56eb2fc; outSize:0xb56eb300; timeOut:10000;
SKLTN :DEBUG1:IN FunctionC PID:0xff8; count:2; fromProcess:SkeltonTest2; toProcess:SkeltonTest3;
　　　　　　　→　PROCESS Dによる実行関数の呼び出し
SKLTN :DEBUG1: NOW CALL FunctionStubC count:1; from:SkeltonTest3; to:SkeltonTest1;
STUB  :DEBUG1:IN FunctioncStubC PID:0xff8;, count:1; fromProcess:SkeltonTest3; toProcess:SkeltonTest1;
STUB  :DEBUG1:IN IPC_CallStubSync PID:0xff8; funcID:0xfff0001; inData:0xb82080b8; inSize:96; outData:0xb56e4964; outSize:0xb56e4968; timeOut:10000;
　　　　　　　→　PROCESS DによるSTUBの呼び出し
SKLTN :DEBUG1:IN skeltonFuncA PID:0xff8; seqNum:0x2; inData:0xb82080b8; inSize:0x60, outData:0xb571e2fc; outSize:0xb571e300; timeOut:10000;
SKLTN :DEBUG1:IN FunctionA PID:0xff6; count:1; fromProcess:SkeltonTest3; toProcess:SkeltonTest1;
　　　　　　　→　PROCESS Bによる実行関数の呼び出し
SKLTN :DEBUG1: ##### OK COUNT IS 0, SO FINISH IN FunctionA PID:0xff6; #####
SKLTN :DEBUG1:OUT FunctionA PID:0xff6; RET:0x1;
　　　　　　　→　PROCESS Bによる実行関数の戻り
SKLTN :DEBUG1:OUT skeltonFuncA PID:0xff8; seqNum:0x2;
STUB  :DEBUG1:OUT IPC_CallStubSync PID:0xff8; funcID:0xfff0001; outData:0xb82080b8; outSize:80;
　　　　　　　→　PROCESS DによるSTUBの戻り
STUB  :DEBUG1:OUT FunctioncStubC PID:0xff8; RET-CODE:0xa; from:SkeltonTest1; to:SkeltonTest3;
SKLTN :DEBUG1: RETURN FunctionStubC retVal:10; fromRet:SkeltonTest1; toRet:SkeltonTest3;
SKLTN :DEBUG1:OUT FunctionC PID:0xff8; RET:0x1;
　　　　　　　→　PROCESS Dによる実行関数の戻り
SKLTN :DEBUG1:OUT skeltonFuncC PID:0xff7; seqNum:0x2;
STUB  :DEBUG1:OUT IPC_CallStubSync PID:0xff7; funcID:0xfff0003; outData:0xb82080b8; outSize:80;
　　　　　　　→　PROCESS CによるSTUBの戻り
STUB  :DEBUG1:OUT FunctioncStubB PID:0xff7; RET-CODE:0xc; from:SkeltonTest3; to:SkeltonTest2;
SKLTN :DEBUG1: RETURN FunctionStubB retVal:12; fromRet:SkeltonTest3; toRet:SkeltonTest2;
SKLTN :DEBUG1:OUT FunctionB PID:0xff7; RET:0x1;
　　　　　　　→　PROCESS Cによる実行関数の戻り
SKLTN :DEBUG1:OUT skeltonFuncB PID:0xff6; seqNum:0x1;
STUB  :DEBUG1:OUT IPC_CallStubSync PID:0xff6; funcID:0xfff0002; outData:0xb82080b8; outSize:80;
　　　　　　　→　PROCESS BによるSTUBの戻り
STUB  :DEBUG1:OUT FunctioncStubA PID:0xff6; RET-CODE:0xb; from:SkeltonTest2; to:SkeltonTest1;
SKLTN :DEBUG1: RETURN FunctionStubA retVal:11; fromRet:SkeltonTest2; toRet:SkeltonTest1;
SKLTN :DEBUG1:OUT FunctionA PID:0xff6; RET:0x1;
　　　　　　　→　PROCESS Bによる実行関数の戻り
SKLTN :DEBUG1:OUT skeltonFuncA PID:0xff8; seqNum:0x1;
STUB  :DEBUG1:OUT IPC_CallStubSync PID:0xff8; funcID:0xfff0001; outData:0xb82080b8; outSize:80;
　　　　　　　→　PROCESS DによるSTUBの戻り
STUB  :DEBUG1:OUT FunctioncStubC PID:0xff8; RET-CODE:0xa; from:SkeltonTest1; to:SkeltonTest3;
SKLTN :DEBUG1: RETURN FunctionStubC retVal:10; fromRet:SkeltonTest1; toRet:SkeltonTest3;
SKLTN :DEBUG1:OUT FunctionC PID:0xff8; RET:0x1;
　　　　　　　→　PROCESS Dによる実行関数の戻り
SKLTN :DEBUG1:OUT skeltonFuncC PID:0xff7; seqNum:0x1;
STUB  :DEBUG1:OUT IPC_CallStubSync PID:0xff7; funcID:0xfff0003; outData:0xb82080b8; outSize:80;
　　　　　　　→　PROCESS CによるSTUBの戻り
STUB  :DEBUG1:OUT FunctioncStubB PID:0xff7; RET-CODE:0xc; from:SkeltonTest3; to:SkeltonTest2;
SKLTN :DEBUG1: RETURN FunctionStubB retVal:12; fromRet:SkeltonTest3; toRet:SkeltonTest2;
SKLTN :DEBUG1:OUT FunctionB PID:0xff7; RET:0x1;
　　　　　　　→　PROCESS Cによる実行関数の戻り
SKLTN :DEBUG1:OUT skeltonFuncB PID:0xff5; seqNum:0x1;
STUB  :DEBUG1:OUT IPC_CallStubSync PID:0xff5; funcID:0xfff0002; outData:0xb82080b8; outSize:80;
　　　　　　　→　PROCESS AによるSTUBの戻り
STUB  :DEBUG1:OUT FunctioncStubA PID:0xff5; RET-CODE:0xb; from:SkeltonTest2; to:StubTest1;
STUB  :DEBUG1: ##### OK SUCCESS TO RETURN SYNC FUNC RET-VAL:0xb; fromRet:SkeltonTest2; toRet:StubTest1; #####
SKLTN :DEBUG1:OUT SkeltonTest1 PID:0xff6;
MAIN  :DEBUG1:RETURN SkeltonTest PID:0xff6;
MAIN  :DEBUG1:NOW PROCESS IS EXITED PID:0xff6; MASTER:0; SKELTON:1; STUB:1;
SKLTN :DEBUG1:OUT SkeltonTest3 PID:0xff8;
MAIN  :DEBUG1:RETURN SkeltonTest PID:0xff8;
MAIN  :DEBUG1:NOW PROCESS IS EXITED PID:0xff8; MASTER:0; SKELTON:1; STUB:1;
MAIN  :DEBUG1:RETURN FROM WAIT PID:0xff6; STATUS:0x0;
MAIN  :DEBUG1:RETURN FROM WAIT PID:0xff8; STATUS:0x0;
SKLTN :DEBUG1:OUT SkeltonTest2 PID:0xff7;
MAIN  :DEBUG1:RETURN SkeltonTest PID:0xff7;
MAIN  :DEBUG1:NOW PROCESS IS EXITED PID:0xff7; MASTER:0; SKELTON:1; STUB:1;
MAIN  :DEBUG1:RETURN FROM WAIT PID:0xff7; STATUS:0x0;
STUB  :DEBUG1:OUT StubTestA PID:0xff5;
MAIN  :DEBUG1:RETURN SkeltonTest PID:0xff5;
MAIN  :DEBUG1:NOW PROCESS IS EXITED PID:0xff5; MASTER:0; SKELTON:0; STUB:1;
MAIN  :DEBUG1:RETURN FROM WAIT PID:0xff5; STATUS:0x0;
MAIN  :DEBUG1:END WAIT CHILD PROCESS TO EXIT PID:0xff4;
MAIN  :DEBUG1:NOW PROCESS IS EXITED PID:0xff4; MASTER:1; SKELTON:0; STUB:0;



　２：ライブラリを使ってIPRPCプログラミング

　　・実行関数のラッパー関数の実装
　　　目的の機能を実現するための実行関数を呼び出すラッパー関数を実装する必要があ
　　　る。ラッパー関数の関数仕様は以下に規定されるものでなければならない。

　　　IpcResult_t (*IPC_SkeltonFunc_t)(
　　　　　　uint32_t processId, 
　　　　　　uint32_t seqNum, 
　　　　　　void *inData ,
　　　　　　uint32_t inSize, 
　　　　　　void **outData, 
　　　　　　int32_t *outSize, 
　　　　　　uint32_t timeOut);

　　　上記テストプログラムでは以下のように実装されている。

static RpcResult_t skeltonFuncA(uint32_t processId, uint32_t seqNum, void *inData ,uint32_t inSize, void **outData, int32_t *outSize, uint32_t timeOut) {
　　　　　....
	if((ret = IPC_Unmarshal(inData, inSize, inParam, 1024*10)) != RPC_SUCCESS) {
　　　　　....
		return IPC_FATAL_ERROR;
	}
	fromPid = *((uint32_t*)((RpcParamData_t*)inParam)[0].paramData);
	count = *((uint32_t*)((RpcParamData_t*)inParam)[1].paramData);
	memcpy(fromProcess,((RpcParamData_t*)inParam)[2].paramData,((RpcParamData_t*)inParam)[2].paramSpec.paramLeng);
	fromProcess[((RpcParamData_t*)inParam)[2].paramSpec.paramLeng] = 0;
	memcpy(toProcess, ((RpcParamData_t*)inParam)[3].paramData, ((RpcParamData_t*)inParam)[3].paramSpec.paramLeng);
	toProcess[((RpcParamData_t*)inParam)[3].paramSpec.paramLeng] = 0;
	if((ret = FunctionA(count,fromProcess, toProcess,  &retVal, fromRet, toRet)) != RPC_SUCCESS) {
　　　　　....
		return IPC_FATAL_ERROR;
	}
	if((ret = setSkeltonParam(retVal, fromRet, toRet, retParam, outData, outSize)) != RPC_SUCCESS) {
　　　　　....
		return IPC_FATAL_ERROR;
	}
　　　　　....
	return RPC_SUCCESS;
}

　　　ここでは以下の３つの事柄を行っている。
　　　　・入力パラメタを変換し実行関数に渡せる形式にする。
　　　　　　　→IPC_UnMarshal関数を使用する。
　　　　・実行関数の呼び出し。
　　　　　　　→FunctionAの呼び出し
　　　　・実行関数からの出力パラメタを変換し呼び出し元プロセスに渡せる形式にする
　　　　　　　→IPC_Marshal関数を使用する。上記プログラムではsetSkeltonParam内
　　　　　　　　で呼ばれている。


　　・実行関数のラッパー関数の登録
　　　SKELTON側に実行関数のラッパー関数をデータベースに登録しなければならない。
　　　登録するためには以下の関数を使用する

　　　RpcResult_t IPC_SkeltonRegisterFunction(
　　　　　　uint32_t funcId,
　　　　　　IPC_SkeltonFunc_t func,
　　　　　　IPC_SkeltonCancelFunc_t cancelFunc);

　　　上記テストプログラムでは以下のように実装されている。

RpcResult_t SkeltonTest1(void) {
　　　　　....
	if((ret = IPC_RegisterFuncDBEntry(IPC_FUNCTION_A_FUNC_ID, pid, skeltonFuncA,skeltonFuncCancelA)) != RPC_SUCCESS) {
　　　　　....
	}
　　　　　....
	return RPC_SUCCESS;
}

　　　なお、上記テストプログラムではキャンセル関数のラッパー関数も登録しているが、
　　　とりあえずはNULLでも構わない。
　　　上記ではデータベースのライブラリ関数を使って登録をしているが、実装する際は
　　　スケルトンの登録関数を使うこと。

　　・STUBのラッパー関数の実装
　　　STUBの呼び出し(RPC)は以下のように定義されている（同期RPCの場合）。

　　　RpcResult_t IPC_CallStubSync(
　　　　　　uint32_t funcID, 
　　　　　　void *inData, 
　　　　　　uint32_t inSize, 
　　　　　　void **outData, 
　　　　　　uint32_t *outSize, 
　　　　　　uint32_t timeOut, 
　　　　　　uint32_t *errCode);

　　　この関数を呼び出すためのラッパー関数を実装する必要がある。上記テストプログ
　　　ラムでは以下のように実装している。

RpcResult_t FunctionStubA(uint32_t count, char *fromProcess, char *toProcess, uint32_t *retVal, char *fromRet, char *toRet) {
　　　　　....
	if((ret = setStubParam(inData, pid, count, fromProcess, toProcess, &outData, &outSize)) != RPC_SUCCESS) {
		return ret;
	}
	timeOut = 1000*10;
	if((ret = IPC_CallStubSync(IPC_FUNCTION_B_FUNC_ID, outData, outSize, &retData, &retSize,timeOut, &errCode)) != RPC_SUCCESS) {
　　　　　....
		return ret;
	}
　　　　　....
	if((ret = IPC_Unmarshal(retData, retSize, retParam, retParamSizee)) != RPC_SUCCESS) {
　　　　　....
		return ret;
	}
	*retVal = *((uint32_t*)((RpcParamData_t*)retParam)[0].paramData);
	memcpy(fromRet,((RpcParamData_t*)retParam)[1].paramData,((RpcParamData_t*)retParam)[1].paramSpec.paramLeng);
	fromRet[((RpcParamData_t*)retParam)[1].paramSpec.paramLeng] = 0;
	memcpy(toRet, ((RpcParamData_t*)retParam)[2].paramData, ((RpcParamData_t*)retParam)[2].paramSpec.paramLeng);
	toRet[((RpcParamData_t*)retParam)[2].paramSpec.paramLeng] = 0;
　　　　　....
	return ret;
}

　　　ここでは以下の３つの事柄を行っている。
　　　　・実行関数への入力パラメタを変換し相手プロセスに渡せる形式にする。
　　　　　　　→IPC_Marshal関数を使用する。上記プログラムではsetStubParam内で呼ば
　　　　　　　　れている。
　　　　・STUBの呼び出し(RPC)
　　　　　　　→IPC_CallStubSyncの呼び出し
　　　　・実行関数からの出力パラメタを変換し呼び出し元の関数に渡せる形式にする。
　　　　　　　→IPC_Unmarshal関数を使用する。

　　・呼び出し元プロセス用の関数、呼び出し先プロセス用の関数を実装
　　　呼び出し元および呼び出し先のプロセスを実行する関数は以下のライブラリ初期化
　　　関数を実行する必要がある。

　　　RpcResult_t IPC_InitIprpc(
　　　　　　RpcBool_t masterProcess, 
　　　　　　RpcBool_t useSkelton, 
　　　　　　RpcBool_t useStub, 
　　　　　　RpcLogLevel_t logLevel);

　　　この関数を呼び出したあと、呼び出し先プロセス用関数であれば、実行関数のラッ
　　　パー関数をSKELTONに登録し、呼び出し元プロセス用関数であれば、STUBのラッパー
　　　関数を呼び出せばよい。



■　CONFIGURATION

　コンフィグレーションについてはINSTALLファイルに記載されている。コンフィグレー
ションの情報はINSTALLファイルを参照すること。



■　REFERENCE MANUAL

　このライブラリのレファレンスマニュアルはREFERENCEファイルに記載されている。レ
ファレンスマニュアルはREFERENCEファイルを参照すること。



■　LICENSE

   This software is exhibited subject to observe terms and conditions of the 
 following article.

Copyright (C) 2012-2013 by Hiroyuki KAJIURA. All rights reserved.

Redistribution and use in source and binary forms, with or without modification, 
are permitted provided that the following conditions are met:

    1:Redistributions of source code must retain the above copyright notice, 
      this list of conditions and the following disclaimer.
    2:Redistributions in binary form must reproduce the above copyright notice, 
      this list of conditions and the following disclaimer in the documentation 
      and/or other materials provided with the distribution.
    3:Neither the name of copyright owner nor the names of its contributors 
      may be used to endorse or promote products derived from this software 
      without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
OF THE POSSIBILITY OF SUCH DAMAGE.



