マルチスレッド自動モードでは、RPC ライブラリはスレッドを作成し、管理することができます。サービス開発者が新規インタフェース呼び出し、rpc_control() を呼び出し、svc_run() を呼び出す前にサーバーをマルチスレッド自動モードにします。このモードでは、プログラマはサービス手続きがマルチスレッド対応であることを確認するだけで十分です。
rpc_control() の使用によって、アプリケーションでグローバル RPC 属性を設定できます。現在はサービス側の操作しかサポートしていません。 表 4-10 は、自動モード用に定義された rpc_control() 操作を示します。追加の情報については、rpc_control(3NSL) のマニュアルページを参照してください。
表 4-10 rpc_control() ライブラリルーチン
マルチスレッドモードの設定 |
|
マルチスレッドの取得 |
|
最大スレッド数の設定 |
|
最大スレッド数の取得 |
|
現在アクティブなスレッドの合計数 |
|
RPC ライブラリ作成のスレッドの累積数 |
|
RPC ライブラリ内の thr_create エラー数 |
表 4-10 の get 演算は、RPC_SVC_MTMODE_GET() 以外はすべて、自動マルチスレッドモードにだけ適用されます。マルチスレッド・ユーザー・モードまたはデフォルトのシングル・スレッド・モードで使用する場合には、演算の結果は定義されません。
デフォルトでは、RPC ライブラリが一度に作成できるスレッドの最大数は 16 です。サーバーが 16 以上のクライアント要求を同時に処理する必要がある場合には、スレッドの最大数を指定して設定する必要があります。このパラメータは、サーバーによっていつでも設定することができ、これによってサーバー開発者はサーバーによって使用されるスレッドリソースの上限を設定できます。例 4-39 は、マルチスレッド自動モードに作成された RPC プログラムの例です。この例では、スレッドの最大数は 20 に設定されています。
マルチスレッドのパフォーマンスは、関数 svc_getargs() が、NULLPROCS 以外の手続きによって呼び出されるごとに、引き数 (この場合には xdr_void())がない場合でも改善されていきます。これはマルチスレッド自動モードとマルチスレッドユーザーモード両方の場合においてです。詳細は、rpc_svc_calls(3NSL) のマニュアルページを参照してください。
例 4-39 は、マルチスレッド自動モードでのサーバーを示したものです。
RPC マルチスレッド対応アプリケーションを作成する場合は常に、スレッドライブラリ内でリンクしなければなりません。コンパイルコマンドで -lthread を指定して、スレッドライブラリを最後にリンクするようにしなければなりません。
次のように入力して例 4-39 のプログラムを作成します。
$ cc time_svc.c -lnsl -lthread |
#include <stdio.h> #include <rpc/rpc.h> #include <synch.h> #include <thread.h> #include "time_prot.h" void time_prog(); main(argc, argv) int argc; char *argv[]; { int transpnum; char *nettype; int mode = RPC_SVC_MT_AUTO; int max = 20; /* スレッド最大数を 20 に設定 */ if (argc > 2) { fprintf(stderr, "usage: %s [nettype]¥n", argv[0]); exit(1); } if (argc == 2) nettype = argv[1]; else nettype = "netpath"; if (!rpc_control(RPC_SVC_MTMODE_SET, &mode)) { printf("RPC_SVC_MTMODE_SET: failed¥n"); exit(1); } if (!rpc_control(RPC_SVC_THRMAX_SET, &max)) { printf("RPC_SVC_THRMAX_SET: failed¥n"); exit(1); } transpnum = svc_create( time_prog, TIME_PROG, TIME_VERS, nettype); if (transpnum == 0) { fprintf(stderr, "%s: cannot create %s service.¥n", argv[0], nettype); exit(1); } svc_run(); } /* * サーバーのディスパッチプログラムです。RPC サーバーライブラリは、 * サーバーのディスパッチャルーチン time_prog () を実行するスレッドを * 作成します。RPC ライブラリがスレッドを廃棄した後に行われます。 */ static void time_prog(rqstp, transp) struct svc_req *rqstp; SVCXPRT *transp; { switch (rqstp->rq_proc) { case NULLPROC: svc_sendreply(transp, xdr_void, NULL); return; case TIME_GET: dotime(transp); break; default: svcerr_noproc(transp); return; } } dotime(transp) SVCXPRT *transp; { struct timev rslt; time_t thetime; thetime = time((time_t *)0); rslt.second = thetime % 60; thetime /= 60; rslt.minute = thetime % 60; thetime /= 60; rslt.hour = thetime % 24; if (!svc_sendreply(transp, xdr_timev,(caddr_t) &rslt)) { svcerr_systemerr(transp); } } |
例 4-40 は、サーバーの time_prot.h ヘッダーファイルを示します。
include <rpc/types.h> struct timev { int second; int minute; int hour; }; typedef struct timev timev; bool_t xdr_timev(); #define TIME_PROG 0x40000001 #define TIME_VERS 1 #define TIME_GET 1 |