Многопотоковый RPC сервер в среде White Box Linux 3 (RHEL 3)

Насколько известно автору, SUN RPC не был полностью портирован в среду Linux , включая Red Hat Enterprise Linux AS/ES 3. Невозможность распараллеливать вызов удаленных процедур является весьма серьезной проблемой для промышленной ОС, и в данной статье обсуждается один из способов ее решения

[Борис Державец (dba477 AT list.ru)]

Насколько известно автору, SUN RPC не был полностью портирован в среду Linux , включая Red Hat Enterprise Linux AS/ES 3. Ключ -А утилиты RPCGEN , позволяющий в среде SunOS ,скомпилировать многопотоковый RPC сервер не поддерживается в среде Red Hat Linux 9,а также и в среде RHEL AS/ES 3. Невозможность распараллеливать вызов удаленных процедур является весьма серьезной проблемой для промышленной ОС, сравните , например, с Sun RPC для SunOS или DCE RPC для HP-UX.

Производительность Oracle Advanced Replication, использующих отложенные либо немедленные RPC вызовы , в среде не поддерживающей многопотоковые RPC сервера , будет заведомо худшей чем , например, под SunOS.

В статье приводится технология изменения кода заглушки сервера, позволяющая продемонстрировать на конкретном примере из [2] , как распараллелить код square_svc.c в среде White Box Linux 3 (RHEL 3) и собрать многопотоковый RPC сервер.

Подход никаким образом не связан с конкретным примером ( шаблон square.x) - это универсальные изменения, вносимые в файл заглушки сервера sample_svc.c ( для произвольного шаблона sample.x) ,базированные на Posix Threads API и делающие код заглушки многопотоковым.

Заметим, что откомпилировать square_svc.c из [1] в среде White Box Linux 3 не удается. Сравнение версии glibc показывает :

          2.3.2-11.9 (RHL 9)
          2.3.2-95.20 (White Box Linux 3)
Ниже приведен модифицированный код square_svc.c, позволяющий откомпилировать многопотоковый RPC сервер в среде White Box Linux 3 (RHEL 3) следуя [1].

/*                                                          square_svc.c
 * Please do not edit this file.
 * It was generated using rpcgen.
 */
#include "square.h"
#include <stdio.h>
#include <stdlib.h>
#include <rpc/pmap_clnt.h>
#include <string.h>
#include <memory.h>
#include <sys/socket.h>
#include <netinet/in.h>
#ifndef SIG_PF
#define SIG_PF void(*)(int)
#endif
struct thr_data
{
struct svc_req *rqstp;
SVCXPRT *transp;
} ;

pthread_t p_thread;
pthread_attr_t attr;
/* Procedure to be run by thread */
void *
serv_request(void *data)
{
struct thr_data *ptr_data = (struct thr_data *)data;
 union {
                square_in squareproc_2_arg;
   } argument;
 union {
                square_out squareproc_2_res;
   } result;
   bool_t retval;
   xdrproc_t _xdr_argument, _xdr_result;
   bool_t (*local)(char *, void *, struct svc_req *);
struct svc_req *rqstp = ptr_data->rqstp;
register SVCXPRT *transp = ptr_data->transp;
        switch (rqstp->rq_proc) {
        case NULLPROC:
                (void) svc_sendreply (transp, (xdrproc_t) xdr_void, (char *)NULL);
                return;
        case SQUAREPROC:
                _xdr_argument = (xdrproc_t) xdr_square_in;
                _xdr_result = (xdrproc_t) xdr_square_out;
                local = (bool_t (*) (char *, void *,  struct svc_req *))squareproc_2_svc;
                break;
        default:
                svcerr_noproc (transp);
                return;
        }
        memset ((char *)&argument, 0, sizeof (argument));
        if (!svc_getargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) {
                svcerr_decode (transp);
                return;
        }
        retval = (bool_t) (*local)((char *)&argument, (void *)&result, rqstp);
 if (retval > 0 && !svc_sendreply(transp, (xdrproc_t) _xdr_result, (char *)&result))
   {
                svcerr_systemerr (transp);
       }
        if (!svc_freeargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) {
                fprintf (stderr, "%s", "unable to free arguments");
                exit (1);
        }
        if (!square_prog_2_freeresult (transp, _xdr_result, (caddr_t) &result))
                fprintf (stderr, "%s", "unable to free results");
        return;
}
/* 
New code for square_prog_2
*/
static void
square_prog_2(struct svc_req *rqstp, register SVCXPRT *transp)
{
struct data_str
{
struct svc_req *rqstp;
SVCXPRT *transp;
} *data_ptr=(struct data_str*)malloc(sizeof(struct data_str));
{
data_ptr->rqstp = rqstp;
data_ptr->transp = transp;
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
pthread_create(&p_thread,&attr,serv_request,(void *)data_ptr);
 }
}
int
main (int argc, char **argv)
{
	register SVCXPRT *transp;
	pmap_unset (SQUARE_PROG, SQUARE_VERS);
	transp = svcudp_create(RPC_ANYSOCK);
	if (transp == NULL) {
		fprintf (stderr, "%s", "cannot create udp service.");
		exit(1);
	}
	if (!svc_register(transp, SQUARE_PROG, SQUARE_VERS, square_prog_2, IPPROTO_UDP)) {
		fprintf (stderr, "%s", "unable to register (SQUARE_PROG, SQUARE_VERS, udp).");
		exit(1);
	}
	transp = svctcp_create(RPC_ANYSOCK, 0, 0);
	if (transp == NULL) {
		fprintf (stderr, "%s", "cannot create tcp service.");
		exit(1);
	}
	if (!svc_register(transp, SQUARE_PROG, SQUARE_VERS, square_prog_2, IPPROTO_TCP)) {
		fprintf (stderr, "%s", "unable to register (SQUARE_PROG, SQUARE_VERS, tcp).");
		exit(1);
	}
	svc_run ();
	fprintf (stderr, "%s", "svc_run returned");
	exit (1);
	/* NOTREACHED */
}
Ccылки.
  1. http://www.linuxgazette.com/node/9005
  2. W. Richard Stevens UNIX: Network Programming v 2.Interprocess communications Prentice Hall,1999

[ опубликовано 03/06/2005 ]

Борис Державец (dba477 AT list.ru) - Многопотоковый RPC сервер в среде White Box Linux 3 (RHEL 3)   Версия для печати