Komunikacja między procesami w Unixie
int * print_hello_l(void *argp, CLIENT *clnt) { static int clnt_res;
memset((char *)Sclntres, 0, sizeof (clnt_res)); if (clnt_call(clnt, print_hello,
(xdrproc_t) xdr_void, (caddr_t) argp, (xdrproc_t) xdr_int, (caddr_t) &clnt_res, TIMEOUT) !- RPC_SUCCESS) { return (NULL);
}
return (Sclnt res);
Ponieważ korzystamy z programu rpcgen po to, aby zmniejszyć złożoność procedur RPC, nie zajmiemy się formalnie funkcją clnt_call. Do funkcji tej (to właśnie ona wykonuje wywołanie zdalnej procedury) jest przekazywany uchwyt klienta, wygenerowany wcześniejszym wywołaniem funkq'i clnt_creat. Drugi argument clnt_call, pobierany z pliku hello. h, to zdefiniowana tam stała print_hello. Trzecim i piątym są wskaźniki do procedur kodującej i dekodującej XDR. Pomiędzy tymi argumentami wciśnięte jest odwołanie do pierwszego argumentu, który zostanie przekazany do zdalnej procedury przez proces-serwer. Szóstym argumentem funkcji jest wskaźnik na miejsce, do którego trafią zwrócone dane. Siódmym i ostatnim jest wartość TIMEOUT. Choć w komentarzach znajduje się informacja, iż nie powinno się edytować tego pliku (na ogół zalecenie to jest słuszne), wartość TIMEOUT można zmieniać od domyślnej 25 do innych rozsądnych wartości maksymalnych.
Kod w hello_svc.c jest o wiele bardziej złożony i nie zostanie zaprezentowany ze względu na ograniczone rozmiary tej publikami. Niemniej jednak autor gorąco zachęca wszystkich zainteresowanych czytelników do otworzenia pliku hello.x, a także do wygenerowania i obejrzenia pliku hello_svc. c. W tym miejscu wystarczy odnotować jedynie, iż plik ten zawiera kod procesu-serwera. Raz uruchomiony będzie pozostawał w pamięci. Powiadomiony przez klienta, uruchomi funkcję print_hello_l_svc.
Programy RPC są ze względu na swoją naturę bardzo trudne do uruchamiania. Jednym z prostszych sposobów uruchamiania i testowania aplikacji RPC, powiedzmy za pomocą dbx, jest skonsolidowanie programu klienta i serwera z wygenerowanymi przez rpcgen procedurami wejścia. Aby to zrobić, należy umieścić w komentarzach odwołania RPC z programu klienta. Jeżeli do rpcgen przekaże się opcję-C, to trzeba odpowiednio zmienić nazwę funkqi (tj. dodać przyrostek _svc). Dodatkowo konieczne może się okazać rzutowanie na odpowiedni typ (tj. svc_req *) argumentu ze wskaźnikiem na typ Client. Po zaimplementowaniu tych zmian odpowiednimi dyrektywami preprocesora otrzymamy następujący plik hello_client. c:
#include <stdio.h> łinclude <stdlib,h>
łinclude "hello.h" /*** wygenerowany przez rpcgen na podstawie hello.x */
void mainfint argc, char *argv[)) (
/* * * TO SAMO CO WCZEŚNIEJ * * */
/*
* generowanie uchwytu klienta */
iifndef DEBUG
if ((Client - clnt_create(server, DISPLAYJPRG, DISPLAY_VER, "visible"))
(CLIENT *) NULL) {
clnt_pcreateerror(server); -
l
return_value = print_hello_l((void *) £filier, Client);
#else
return_value - print_hello_l_svc((void *) Sfiller, (svc_req *) Client) tendif
if (*return_value)
printf ("Mis ja spełniona\n"); else
printf ("Nie udało sie\n")j exit (0);
Możemy skompilować tę zmienioną wersję aplikacji za pomocą sekwencji poleceń pokazanej na ilustracji 9.18. Ponieważ nie ma odwołań do żadnych bibliotek, nie ma potrzeby konsolidowania plików obiektowych z biblioteką libnsl. Kompilator należy uruchomić ze znacznikiem -g (aby została wygenerowana tablica z danymi dla programu dbx) oraz -DDEBUG (aby zdefiniować stałą preprocesora DEBUG).
Skompilować za pomocą cc, definiując stałą DEBUG i nakazując wygenerowanie tablicy z informacjami o symbolach.
% CC -DDEBUG -g hello_client.c hello_server.c.^-:-
hello_client.c:
"hello_client.c", linę 9: warning: Client used but not set hello server.c:
"hello_server.c", linę 9: warning: filier not used "hello server.c", linę 9: warning: req not used
% dbx a.out
Reading symbolic information for a.out
Reading symbolic information for rtld /usr/lib/ld.so.1
Reading symbolic information for ./lib/libc.so.l
Reading symbolic information for f/lib/libdl.so.1
(dbx) tracę ^-----—■-- Pokazać każdą instrukcję
(2) tracę przed wykonaniem.
(dbx) run morpheus Running: a.out morpheus entering function main
tracę: |
16 |
if largc != 2){ |
tracę: |
20 |
server = argv[l]; |
tracę: |
33 |
return value « print_hello _l_svc ((void *) Sfiller |
267