この節で説明する内容は、(デフォルトの) シングルスレッドのモードで RPC を実行する場合にだけ適用されます。
RPC 要求をサービスしたり、その他のアクティビティを実行したりするプロセスでは、svc_run() を呼び出せない場合があります。他のアクティビティで定期的にデータ構造を更新する場合は、プロセスから svc_run() を呼び出す前に SIGALRM 信号をセットできます。そうすると、シグナルハンドラがデータ構造を処理してから svc_run() に制御を戻します。
プロセスから svc_run() をバイパスして直接ディスパッチャにアクセスするには、svc_getreqset() を呼び出します。プロセスには、待っているプログラムに結合したトランスポート端点のファイル記述子が指定されている必要があります。その場合、プロセスは自分で poll() を呼び出して、RPC ファイル記述子と自身の記述子の両方で要求を待つことができます。
例 5–1 には svc_run() を示します。 svc_pollset は、_rpc_select_to_poll() の呼び出しを通して svc_fdset() から派生した pollfd 構造体の配列です。この配列は、RPC ライブラリルーチンのどれかが呼び出されるたびに変わる可能性があります。そのたびに記述子がオープンされ、クローズされるからです。poll() がいくつかの RPC ファイル記述子への RPC 要求の到着を確認すると、svc_getreq_poll() が呼び出されます。
__rpc_dtbsize() と __rpc_select_to_poll () は、SVID の一部ではありませんが、libnsl ライブラリで使用できます。Solaris 以外でも実行できるように、これらの関数を作成するために、関数の仕様を説明します。
ビットフラグとして fd_set ポインタとチェックすべきビット数が指定されます。 関数 __rpc_select_to_poll では、指定された pollfd 配列を RPC が使用するために初期化するようにします。RPC は、入力イベントだけをポーリングします。初期化された pollfd スロット数が返されます。この関数の引数は次のとおりです。
int __rpc_select_to_poll(int fdmax, fd_set *fdset, struct pollfd *pollset)
関数 __rpc_dtbsize() は、getrlimit() 関数を呼び出し、新しく作成された記述子にシステムが割り当てる最大値を決定します。結果は、効率化のためにキャッシュされます。
この節の SVID ルーチンについての詳細は、rpc_svc_calls(3NSL) および poll(2) のマニュアルページを参照してください。
void svc_run() { int nfds; int dtbsize = __rpc_dtbsize(); int i; struct pollfd svc_pollset[fd_setsize]; for (;;) { /* * 要求待ちするサーバー fd があるかどうかをチェック */ nfds = __rpc_select_to_poll(dtbsize, &svc_fdset, svc_pollset); if (nfds == 0) break; /* 要求待ちの fd がないので終了 */ switch (i = poll(svc_pollset, nfds, -1)) { case -1: /* * エラーが起こった場合は、poll() ではなく、シグナルハンドラなど * 外部イベントによるものと考えて、無視して継続する */ case 0: continue; default: svc_getreq_poll(svc_pollset, i); } } } |