ONC+ 開発ガイド

自動マルチスレッド対応モード

マルチスレッド自動モードでは、RPC ライブラリはスレッドを作成し、管理することができます。サービス開発者が新規インタフェース呼び出し、rpc_control() を呼び出し、svc_run() を呼び出す前にサーバーをマルチスレッド自動モードにします。このモードでは、プログラマはサービス手続きがマルチスレッド対応であることを確認するだけで十分です。

rpc_control() の使用によって、アプリケーションでグローバル RPC 属性を設定できます。現在はサービス側の操作しかサポートしていません。次の表は、自動モード用に定義された rpc_control() 操作を示します。詳細は rpc_control(3NSL) マニュアルページを参照してください。

表 7–1 rpc_control ライブラリルーチン

ルーチン 

説明 

RPC_SVC_MTMODE_SET()

マルチスレッドモードの設定 

RPC_SVC_MTMODE_GET()

マルチスレッドの取得 

RPC_SVC_THRMAX_SET()

最大スレッド数の設定 

RPC_SVC_THRMAX_GET()

最大スレッド数の取得 

RPC_SVC_THRTOTAL_GET ()

現在アクティブなスレッドの合計数  

RPC_SVC_THRCREATES_GET ()

RPC ライブラリ作成のスレッドの累積数 

RPC_SVC_THRERRORS_GET ()

RPC ライブラリ内の thr_create() エラー数


注 –

表 7–1 の get 演算は、RPC_SVC_MTMODE_GET() 以外はすべて、自動マルチスレッドモードにだけ適用されます。マルチスレッドユーザーモードまたはデフォルトのシングルスレッドモードで使用すると、演算の結果が定義されません。


デフォルトでは、RPC ライブラリが一度に作成できるスレッドの最大数は 16 です。サーバーが 16 以上のクライアント要求を同時に処理する必要がある場合には、スレッドの最大数を指定して設定する必要があります。このパラメータは、サーバーによっていつでも設定できます。これによって、サーバー開発者はサーバーによって使用されるスレッドリソースの上限を設定できます。例 7–1 は、マルチスレッド自動モードに作成された RPC プログラムの例です。この例では、スレッドの最大数は 20 に設定されています。

マルチスレッドのパフォーマンスは、関数 svc_getargs() が、NULLPROCS 以外の手続きによって呼び出されるごとに、引数 (この場合には xdr_void())がない場合でも改善されていきます。これは、マルチスレッド自動モードとマルチスレッドユーザーモードの両方においてです。詳細は、rpc_svc_calls(3NSL) のマニュアルページを参照してください。


注 –

RPC マルチスレッド対応アプリケーションを作成する場合は常に、スレッドライブラリ内でリンクしなければなりません。スレッドライブラリは、コマンド行で最後にリンクする必要があります。そのためには、コンパイルコマンドで -lthread オプションを指定します。


次の例は、マルチスレッド自動モードでのサーバーを示したものです。このプログラムをコンパイルするには、cc time_svc.c -lnsl -lthread を実行します。


例 7–1 マルチスレッド自動モードのサーバー

		#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);
		}
	}

次に、サーバーの time_prot.h ヘッダーファイルを示します。


例 7–2 マルチスレッド自動モード : 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