Apelarea procedurilor de la distanță (rpc - Remote Procedure Call). Proceduri de la distanță: Apel de procedură de la distanță, definiție și caracteristici Pași de execuție RPC

Cursul 4

4.1 Conceptul de apel de procedură de la distanță

Ideea de a apela proceduri de la distanță (Apel de procedură de la distanță - RPC) constă în extinderea mecanismului bine-cunoscut și înțeles de transfer de control și date în cadrul unui program care rulează pe o mașină la transferul de control și date printr-o rețea. Instrumentele de apelare a procedurilor de la distanță sunt concepute pentru a facilita organizarea calculului distribuit. Cea mai mare eficiență a utilizării RPC este atinsă în acele aplicații în care există o comunicare interactivă între componentele de la distanță cu timpi de răspuns rapid și o cantitate relativ mică de date transferate. Astfel de aplicații sunt numite RPC-oriented.

Trăsăturile caracteristice apelării procedurilor locale sunt: ​​asimetria, adică una dintre părțile care interacționează este inițiatorul; sincronicitatea, adică execuția procedurii de apelare se oprește din momentul emiterii cererii și se reia numai după revenirea procedurii apelate.

Implementarea apelurilor de la distanță este mult mai complicată decât implementarea apelurilor de procedură locală. Pentru început, deoarece procedurile de apelare și apelare sunt executate pe mașini diferite, acestea au spații de adrese diferite, iar acest lucru creează probleme la transmiterea parametrilor și a rezultatelor, mai ales dacă mașinile nu sunt identice. Deoarece RPC nu se poate baza pe memoria partajată, aceasta înseamnă că parametrii RPC nu trebuie să conțină pointeri către locații de memorie non-stiva și că valorile parametrilor trebuie copiate de pe un computer pe altul. Următoarea diferență între RPC și un apel local este că folosește neapărat sistemul de comunicare de bază, dar acest lucru nu ar trebui să fie vizibil în mod explicit nici în definirea procedurilor, nici în procedurile în sine. Depărtarea introduce probleme suplimentare. Execuția programului apelant și a procedurii locale apelate pe aceeași mașină este implementată într-un singur proces. Dar implementarea RPC implică cel puțin două procese - câte unul pe fiecare mașină. Dacă una dintre ele se blochează, pot apărea următoarele situații: dacă procedura de apelare se blochează, procedurile apelate de la distanță vor deveni „orfane”, iar dacă procedurile de la distanță se blochează, procedurile de apelare vor deveni „părinți orfani”, așteptând în zadar un răspuns de la procedurile de la distanță.

În plus, există o serie de probleme asociate cu eterogenitatea limbajelor de programare și a mediilor de operare: structurile de date și structurile de apel de procedură acceptate în orice limbaj de programare nu sunt acceptate în același mod în toate celelalte limbaje.


Acestea și alte probleme sunt rezolvate de tehnologia RPC răspândită, care stă la baza multor sisteme de operare distribuite.

Operații RPC de bază

Pentru a înțelege cum funcționează RPC, să luăm în considerare mai întâi efectuarea unui apel de procedură locală pe o mașină obișnuită care rulează offline. Să fie acesta, de exemplu, un apel de sistem

count=read(fd,buf,nbytes);

unde fd este un număr întreg;

buf – matrice de caractere;

nbytes este un număr întreg.

Pentru a efectua apelul, procedura de apelare împinge parametrii pe stivă în ordine inversă. După ce apelul de citire este executat, plasează valoarea returnată într-un registru, mută adresa de returnare și returnează controlul procedurii de apelare, care scoate parametrii din stivă, readucendu-l la starea inițială. Rețineți că în limbajul C, parametrii pot fi apelați fie prin referință (după nume), fie prin valoare (după valoare). În raport cu procedura apelată, parametrii de valoare sunt variabile locale inițializate. Procedura apelată le poate modifica fără a afecta valorile inițiale ale acestor variabile în procedura de apelare.

Dacă un pointer către o variabilă este transmis procedurii apelate, atunci modificarea valorii acestei variabile de către procedura apelată implică modificarea valorii acestei variabile pentru procedura apelată. Acest fapt este foarte semnificativ pentru RPC.

Există, de asemenea, un alt mecanism de transmitere a parametrilor care nu este utilizat în C. Se numește call-by-copy/restore, care necesită apelant să copieze variabilele în stivă ca valori, apoi să le copieze înapoi după ce apelul este efectuat. valorile originale ale procedurii de apelare.

Decizia despre ce mecanism de trecere a parametrilor să fie utilizat este luată de dezvoltatorii limbajului. Uneori depinde de tipul de date transferate. În C, de exemplu, numerele întregi și alte date scalare sunt întotdeauna transmise după valoare, iar tablourile sunt întotdeauna transmise prin referință.

Ideea din spatele RPC este de a face un apel de procedură la distanță să arate cât mai asemănător cu un apel de procedură locală. Cu alte cuvinte, faceți RPC transparent: procedura de apelare nu trebuie să știe că procedura apelată este pe o altă mașină și invers.

RPC realizează transparență în felul următor. Când procedura apelată este de fapt la distanță, o altă versiune a procedurii, numită client stub, este plasată în bibliotecă în locul procedurii locale. La fel ca procedura originală, stub-ul este apelat folosind o secvență de apelare și apare o întrerupere la accesarea nucleului. Numai că, spre deosebire de procedura inițială, nu plasează parametri în registre și nu solicită date de la kernel; în schimb, generează un mesaj care urmează să fie trimis către nucleul mașinii la distanță.

Etapele de execuție RPC

Interacțiunea componentelor software atunci când se efectuează un apel de procedură la distanță este ilustrată în Figura 2.

Figura 2. Apel de procedură de la distanță

După ce stub-ul clientului a fost apelat de către programul client, prima sa sarcină este să umple buffer-ul cu mesajul trimis. În unele sisteme, stub-ul clientului are un singur buffer cu lungime fixă ​​care este umplut de la bun început cu fiecare cerere nouă. În alte sisteme, buffer-ul de mesaje este un grup de buffere pentru câmpurile individuale de mesaje, dintre care unele sunt deja pline. Această metodă este potrivită în special pentru cazurile în care pachetul are un format format dintr-un număr mare de câmpuri, dar valorile multora dintre aceste câmpuri nu se schimbă de la apel la apel.

Parametrii trebuie apoi convertiți în formatul corespunzător și inserați în bufferul de mesaje. În acest moment, mesajul este gata pentru a fi trimis, astfel încât întreruperea apelului nucleului este executată.

Când nucleul capătă controlul, schimbă contextele, salvează registrele procesorului și harta de memorie (manere de pagină) și instalează o nouă hartă de memorie care va fi folosită pentru a rula în modul kernel. Deoarece nucleul și contextele utilizatorului sunt diferite, nucleul trebuie să copieze mesajul exact în propriul spațiu de adrese, astfel încât să-l poată accesa, să-și amintească adresa de destinație (și eventual alte câmpuri de antet) și să-l transmită interfeței de rețea. Acest lucru completează munca din partea clientului. Cronometrul de transmisie este pornit, iar nucleul poate fie să interogheze ciclic pentru un răspuns, fie să transmită controlul către planificator, care va selecta un alt proces de rulat. În primul caz, execuția interogării este accelerată, dar multiprogramarea este absentă.

Pe partea de server, biții de intrare sunt plasați de hardware-ul receptor fie într-un buffer pe cip, fie în RAM. Când toate informațiile au fost primite, este generată o întrerupere. Managerul de întrerupere verifică corectitudinea pachetelor de date și determină la ce stub ar trebui trimis. Dacă niciunul dintre stub-uri nu așteaptă acest pachet, handler-ul trebuie fie să-l tamponeze, fie să-l arunce cu totul. Dacă există un talon în așteptare, mesajul este copiat pe acesta. În final, se efectuează o comutare de context, în urma căreia se restabilesc registrele și harta memoriei, luând valorile pe care le aveau în momentul în care stub-ul a efectuat apelul de recepție.

Acum, ștuțul serverului începe să funcționeze. Dezambalează parametrii și îi împinge în mod corespunzător pe stivă. Când totul este gata, se efectuează un apel către server. După executarea procedurii, serverul transmite rezultatele către client. Pentru a face acest lucru, efectuați toți pașii descriși mai sus, numai în ordine inversă.

Figura 3 prezintă secvența comenzilor care trebuie executate pentru fiecare apel RPC.

Figura 3. Etapele procedurii RPC

) Conceptul de apel de procedură de la distanță

Ideea unui apel de procedură de la distanță (RPC) este de a extinde mecanismul bine-cunoscut și înțeles pentru transferul de control și date într-un program care rulează pe o singură mașină pentru a transfera controlul și datele printr-o rețea. Instrumentele de apelare a procedurilor de la distanță sunt concepute pentru a facilita organizarea calculului distribuit. Cea mai mare eficiență a utilizării RPC este atinsă în acele aplicații în care există o comunicare interactivă între componentele de la distanță cu timpi de răspuns rapid și o cantitate relativ mică de date transferate. Astfel de aplicații sunt numite RPC-oriented.

Trăsăturile caracteristice ale apelării procedurilor locale sunt:

Asimetria, adică una dintre părțile care interacționează este inițiatorul; Sincronicitatea, adică executarea procedurii de apelare se oprește din momentul emiterii cererii și se reia numai după revenirea procedurii apelate.

Implementarea apelurilor de la distanță este mult mai complicată decât implementarea apelurilor de procedură locală. Pentru început, deoarece procedurile de apelare și apelare sunt executate pe mașini diferite, acestea au spații de adrese diferite, iar acest lucru creează probleme la transmiterea parametrilor și a rezultatelor, mai ales dacă mașinile nu sunt identice. Deoarece RPC nu se poate baza pe memoria partajată, aceasta înseamnă că parametrii RPC nu trebuie să conțină pointeri către locații de memorie non-stiva și că valorile parametrilor trebuie copiate de pe un computer pe altul. Următoarea diferență între RPC și un apel local este că folosește neapărat sistemul de comunicare de bază, dar acest lucru nu ar trebui să fie vizibil în mod explicit nici în definirea procedurilor, nici în procedurile în sine. Depărtarea introduce probleme suplimentare. Execuția programului apelant și a procedurii locale apelate pe aceeași mașină este implementată într-un singur proces. Dar implementarea RPC implică cel puțin două procese - câte unul pe fiecare mașină. Dacă una dintre ele se blochează, pot apărea următoarele situații: dacă procedura de apelare se blochează, procedurile apelate de la distanță vor deveni „orfane”, iar dacă procedurile de la distanță se blochează, procedurile de apelare vor deveni „părinți orfani”, așteptând în zadar un răspuns de la procedurile de la distanță.

În plus, există o serie de probleme asociate cu eterogenitatea limbajelor de programare și a mediilor de operare: structurile de date și structurile de apel de procedură acceptate în orice limbaj de programare nu sunt acceptate în același mod în toate celelalte limbaje.

Acestea și alte probleme sunt rezolvate de tehnologia RPC răspândită, care stă la baza multor sisteme de operare distribuite.

Operații RPC de bază

Pentru a înțelege cum funcționează RPC, să luăm în considerare mai întâi efectuarea unui apel de procedură locală pe o mașină obișnuită care rulează offline. Să fie acesta, de exemplu, un apel de sistem

Count=read(fd,buf,nbytes);

unde fd este un număr întreg,
buf - matrice de caractere,
nbytes este un număr întreg.

Pentru a efectua apelul, procedura de apelare împinge parametrii pe stivă în ordine inversă (Figura 3.1). După ce apelul de citire este executat, plasează valoarea returnată într-un registru, mută adresa de returnare și returnează controlul procedurii de apelare, care scoate parametrii din stivă, readucendu-l la starea inițială. Rețineți că în limbajul C, parametrii pot fi apelați fie prin referință (după nume), fie prin valoare (după valoare). În raport cu procedura apelată, parametrii de valoare sunt variabile locale inițializate. Procedura apelată le poate modifica fără a afecta valorile inițiale ale acestor variabile în procedura de apelare.

Dacă un pointer către o variabilă este transmis procedurii apelate, atunci modificarea valorii acestei variabile de către procedura apelată implică modificarea valorii acestei variabile pentru procedura apelată. Acest fapt este foarte semnificativ pentru RPC.

Există, de asemenea, un alt mecanism de transmitere a parametrilor care nu este utilizat în C. Se numește call-by-copy/restore, care necesită apelant să copieze variabilele în stivă ca valori, apoi să le copieze înapoi după ce apelul este efectuat. valorile originale ale procedurii de apelare.

Decizia despre ce mecanism de trecere a parametrilor să fie utilizat este luată de dezvoltatorii limbajului. Uneori depinde de tipul de date transferate. În C, de exemplu, numerele întregi și alte date scalare sunt întotdeauna transmise după valoare, iar tablourile sunt întotdeauna transmise prin referință.

Orez. 3.1. a) Stiva dinainte de executarea apelului de citire;
b) Stiva în timpul executării procedurii;
c) Stiva după revenirea la programul de apelare

Ideea din spatele RPC este de a face un apel de procedură la distanță să arate cât mai asemănător cu un apel de procedură locală. Cu alte cuvinte, faceți RPC transparent: procedura de apelare nu trebuie să știe că procedura apelată este pe o altă mașină și invers.

RPC realizează transparență în felul următor. Când procedura apelată este de fapt la distanță, o altă versiune a procedurii, numită client stub, este plasată în bibliotecă în locul procedurii locale. La fel ca procedura originală, stub-ul este apelat folosind o secvență de apelare (ca în Figura 3.1) și apare o întrerupere la accesarea nucleului. Numai că, spre deosebire de procedura inițială, nu plasează parametri în registre și nu solicită date de la kernel; în schimb, generează un mesaj care urmează să fie trimis către nucleul mașinii la distanță.

Etapele de execuție RPC

Interacțiunea componentelor software la efectuarea unui apel de procedură la distanță este ilustrată în Figura 3.2. După ce stub-ul clientului a fost apelat de către programul client, prima sa sarcină este să umple buffer-ul cu mesajul trimis. În unele sisteme, stub-ul clientului are un singur buffer cu lungime fixă ​​care este umplut de la bun început cu fiecare cerere nouă. În alte sisteme, buffer-ul de mesaje este un grup de buffere pentru câmpurile individuale de mesaje, dintre care unele sunt deja pline. Această metodă este potrivită în special pentru cazurile în care pachetul are un format format dintr-un număr mare de câmpuri, dar valorile multora dintre aceste câmpuri nu se schimbă de la apel la apel.

Parametrii trebuie apoi convertiți în formatul corespunzător și inserați în bufferul de mesaje. În acest moment, mesajul este gata pentru a fi trimis, astfel încât întreruperea apelului nucleului este executată.

Orez. 3.2. Apel de procedură de la distanță

Când nucleul capătă controlul, schimbă contextele, salvează registrele procesorului și harta de memorie (manere de pagină) și instalează o nouă hartă de memorie care va fi folosită pentru a rula în modul kernel. Deoarece nucleul și contextele utilizatorului sunt diferite, nucleul trebuie să copieze mesajul exact în propriul spațiu de adrese, astfel încât să-l poată accesa, să-și amintească adresa de destinație (și eventual alte câmpuri de antet) și să-l transmită interfeței de rețea. Acest lucru completează munca din partea clientului. Cronometrul de transmisie este pornit, iar nucleul poate fie să interogheze ciclic pentru un răspuns, fie să transmită controlul către planificator, care va selecta un alt proces de rulat. În primul caz, execuția interogării este accelerată, dar multiprogramarea este absentă.

Pe partea de server, biții de intrare sunt plasați de hardware-ul receptor fie într-un buffer pe cip, fie în RAM. Când toate informațiile au fost primite, este generată o întrerupere. Managerul de întrerupere verifică corectitudinea pachetelor de date și determină la ce stub ar trebui trimis. Dacă niciunul dintre stub-uri nu așteaptă acest pachet, handler-ul trebuie fie să-l tamponeze, fie să-l arunce cu totul. Dacă există un talon în așteptare, mesajul este copiat pe acesta. În final, se efectuează o comutare de context, în urma căreia se restabilesc registrele și harta memoriei, luând valorile pe care le aveau în momentul în care stub-ul a efectuat apelul de recepție.

Acum, ștuțul serverului începe să funcționeze. Dezambalează parametrii și îi împinge în mod corespunzător pe stivă. Când totul este gata, se efectuează un apel către server. După executarea procedurii, serverul transmite rezultatele către client. Pentru a face acest lucru, efectuați toți pașii descriși mai sus, numai în ordine inversă.

Figura 3.3 arată secvența comenzilor care trebuie executate pentru fiecare apel RPC, iar Figura 3.4 arată ce proporție din timpul total de execuție RPC este cheltuită pentru fiecare dintre cei 14 pași descriși. Testele au fost efectuate pe o stație de lucru cu mai multe procesoare DEC Firefly și, în timp ce prezența a cinci procesoare a afectat în mod necesar rezultatele măsurătorilor, histograma prezentată în figură oferă o idee generală a procesului de execuție RPC.

Orez. 3.3. Pași pentru a efectua o procedură RPC

Orez. 3.4. Distribuția timpului între 14 etape ale execuției RPC

1. Apelarea unui ciot

2. Pregătiți un tampon

3. Parametrii pachetului

4. Completați câmpul titlu

5. Calculați suma de control din mesaj

6. Întreruperea nucleului

7. Coada de pachete pentru execuție

8. Transmiterea unui mesaj către controler prin magistrala QBUS

9. Timp de transmisie Ethernet

10. Primiți pachetul de la controler

11. Procedura de manipulare a întreruperii

12. Calculul sumei de control

13. Schimbarea contextului în spațiul utilizatorului

14. Efectuarea unui server stub

Legătura dinamică

Să luăm în considerare modul în care clientul specifică locația serverului. O metodă de a rezolva această problemă este utilizarea directă a adresei de rețea a serverului în programul client. Dezavantajul acestei abordări este inflexibilitatea sa extremă: la mutarea unui server, la creșterea numărului de servere sau la schimbarea interfeței în toate acestea și multe alte cazuri, este necesar să se recompileze toate programele care au folosit o adresă de server codificată. Pentru a evita toate aceste probleme, unele sisteme distribuite folosesc ceea ce se numește legătură dinamică.

Punctul de plecare pentru legarea dinamică este definiția formală (specificația) a serverului. Specificația conține numele serverului de fișiere, numărul versiunii și o listă de proceduri de service furnizate de acest server clienților (Figura 3.5). Pentru fiecare procedură, este dată o descriere a parametrilor acesteia, indicând dacă acest parametru este de intrare sau de ieșire în raport cu serverul. Unii parametri pot fi atât de intrare cât și de ieșire - de exemplu, o matrice care este trimisă de client către server, modificată acolo și apoi returnată înapoi la client (operație de copiere/restaurare).

Orez. 3.5. Specificația serverului RPC

Specificația formală a serverului este utilizată ca intrare în programul generator de stub, care creează atât stub-uri client, cât și server. Acestea sunt apoi plasate în bibliotecile corespunzătoare. Când un program utilizator (client) apelează orice procedură definită în specificația serverului, procedura stub corespunzătoare este asociată cu codul binar al programului. De asemenea, atunci când un server este compilat, cioturile de server sunt asociate cu acesta.

Când un server pornește, primul lucru pe care îl face este să-și transmită interfața serverului unui program special numit binder.Acest proces, cunoscut sub numele de proces de înregistrare a serverului, presupune ca serverul să-și transmită numele, numărul versiunii, identificatorul unic și un handle la locația serverului.Manerul este independent de sistem și poate fi o adresă IP, Ethernet, X.500 sau o altă adresă și poate conține și alte informații, cum ar fi informații legate de autentificare.

Când un client apelează una dintre procedurile de la distanță pentru prima dată, de exemplu, citire, stub-ul clientului vede că nu este încă conectat la server și trimite un mesaj programului de legătură cu o solicitare de a importa interfața dorită. versiunea serverului dorit. Dacă un astfel de server există, atunci Binder transmite descriptorul și identificatorul unic stub-ului clientului.

Când trimiteți un mesaj cu o solicitare, stub-ul clientului folosește un descriptor ca adresă. Mesajul conține parametri și un identificator unic pe care nucleul serverului îl folosește pentru a direcționa mesajul primit către serverul dorit, dacă există mai mulți dintre aceștia pe această mașină.

Această metodă de import/export de interfețe este foarte flexibilă. De exemplu, pot exista mai multe servere care acceptă aceeași interfață, iar clienții sunt distribuiți aleatoriu pe servere. În cadrul acestei metode, devine posibilă interogarea periodică a serverelor, analizarea performanței acestora și, în caz de defecțiune, oprirea automată, ceea ce crește toleranța generală la erori a sistemului. Această metodă poate suporta și autentificarea clientului. De exemplu, serverul poate determina că poate fi utilizat numai de clienți dintr-o anumită listă.

Cu toate acestea, legarea dinamică are dezavantaje, cum ar fi supraîncărcarea suplimentară (timp) pentru exportul și importul de interfețe. Amploarea acestor costuri poate fi semnificativă, deoarece multe procese client există pentru o perioadă scurtă de timp, iar de fiecare dată când procesul începe, procedura de import a interfeței trebuie efectuată din nou. În plus, în sistemele mari distribuite, programul de liant poate deveni un blocaj, iar crearea mai multor programe cu un scop similar crește, de asemenea, suprasarcina de creare și sincronizare a proceselor.

Semantica RPC în caz de eșecuri

În mod ideal, RPC ar trebui să funcționeze corect chiar și în cazul unor defecțiuni. Luați în considerare următoarele clase de eșec:

Clientul nu poate localiza serverul, de exemplu, dacă serverul dorit eșuează sau pentru că programul client a fost compilat cu mult timp în urmă și a folosit o versiune veche a interfeței serverului. În acest caz, ca răspuns la solicitarea clientului, se primește un mesaj care conține un cod de eroare. Solicitarea de la client către server a fost pierdută. Cea mai simplă soluție este să repeți cererea după un anumit timp. Mesajul de răspuns de la server către client a fost pierdut. Această opțiune este mai complicată decât cea anterioară, deoarece unele proceduri nu sunt idempotente. O procedură idempotentă este o procedură a cărei cerere de execuție poate fi repetată de mai multe ori fără a modifica rezultatul. Un exemplu de astfel de procedură ar fi citirea unui fișier. Dar procedura de retragere a unei anumite sume dintr-un cont bancar nu este idempotentă, iar dacă răspunsul este pierdut, o solicitare repetată poate schimba semnificativ starea contului clientului. O soluție posibilă este de a face toate procedurile idempotente. Cu toate acestea, în practică acest lucru nu este întotdeauna posibil, așa că poate fi folosită o altă metodă - numerotarea secvențială a tuturor solicitărilor de către nucleul clientului. Nucleul serverului își amintește numărul celei mai recente solicitări de la fiecare client și, la primirea fiecărei cereri, analizează dacă această solicitare este primară sau repetată. Serverul s-a prăbușit după ce a primit cererea. Proprietatea idempotității este de asemenea importantă aici, dar, din păcate, abordarea cu numerotarea interogărilor nu poate fi aplicată. In acest caz conteaza

    Java RMI ca tip de apel de procedură la distanță, independent de rețea, de pașii principali de lucru cu acesta și de scopul său. Comparație între programe Java distribuite și nedistribuite. Arhitectură, stub și schelet, referință la distanță și straturi de transport ale Java RMI.

    Pre-compilarea interogărilor SQL la locul de execuție. Folosind instrucțiunea prepareStatement. Utilizați sintaxa definiției apelului pentru a obține valoarea returnată a unei proceduri sau funcție. Crearea instrucțiunilor pentru prelevare la cerere.

    Scopul și schema de lucru. Compozitie si instalare. Specificația procedurii pachetului http.

    Procedurile și funcțiile pot fi definite ca unități de program închise care implementează un anumit algoritm. De fapt, o procedură sau o funcție este aproape un program.

    Configurare automată TCP/IP, configurare dinamică folosind BOOTP. Adrese IP de solicitare/răspuns, pierderea și formatarea mesajelor, fazele BOOTP. Protocolul DHCP este o extensie a protocolului BOOTP. Distribuirea și atribuirea adreselor IP.

    Am întâlnit deja conceptul de recursivitate: relațiile de recurență se găsesc destul de des în expresiile matematice. Recursiunea în definiție constă în faptul că conceptul care se definește este definit prin acest concept însuși.

    1. Introducere 2 2. Prezentare generală a tehnologiei COM 2 2.1. Compoziția unui obiect COM 3 2.2. Interfețe 4 2.3. Proprietățile obiectelor COM 6 2.4. Servere COM 6 2.5. Mecanismul de repartizare 7

    Studiul esenței, principiului de funcționare și scopului principal al bazelor de date la distanță. Model de gestionare a datelor la distanță (model server de fișiere). Tipuri de paralelism. Un declanșator este un mecanism de urmărire a evenimentelor speciale care sunt asociate cu starea bazei de date.

    Pachete metamodel, fapte și securitate. Modelul conceptual al clientului. Un exemplu de funcționare a unei arhitecturi distribuite. Complexitatea implementării.

    Conceptul dll. Să ne amintim procesul de programare în DOS. Convertirea textului sursă în cod mașină a implicat două procese: compilare și legare. În timpul conectării, nu numai declarațiile de funcții și proceduri, ci și codul lor complet au fost plasate în codul programului.

    Funcții pentru lucrul cu protocolul TCP/IP, Socket, Bind, ascultare și acceptare. Descriptor de fișier. Procesele de comunicare. Primirea datelor. Citirea de pe o priză. Scrieți la o priză. Închiderea prizei. Textul programului care creează un server Web în sistemul de operare QNX.

    Accesul utilizatorilor rețelei la mesajele electronice stocate pe server. Descrierea programului, autentificare simplă, autentificare APOP și AUTH. Implementare de functii, manual de utilizare, algoritmi de operare program, interfata grafica.

    Principiul de funcționare al operatorilor principali ai limbajului de programare Turbo-Paskal: operator de atribuire, selecție de caz, salt necondiționat, buclă, captură, compus. Descrierea formală și apelul unei funcții și proceduri. Cerințe pentru lista parametrilor actuali.

    Principiul de funcționare și scopul servlet-urilor Java, importanța acestora în creșterea funcționalității serverelor Web și îmbunătățirea programării acestora, avantajele și dezavantajele utilizării. Modalități de a apela servlet-uri din browser și pagină. Scrieți și citiți atributele sesiunii.

    Arhitectura sistemului de operare Windows NT. Structura sistemului de operare bazată pe microkernel. Subsisteme protejate ale Windows NT.

    Primitive de transmitere a mesajelor de bază în sistemele distribuite. Metode de adresare. Primitive blocante și neblocante. Primitive tamponate și non-tampon.

    Server de aplicații. Partea clientului.

    În urmă cu doi ani, AJAX era o noutate (și cuvântul AJAX în sine nu fusese încă inventat). Acum, aplicațiile web ale căror pagini sunt actualizate din mers sunt la ordinea zilei. Dimpotrivă: este greu de imaginat unele servicii fără AJAX.

    Sintaxă pentru descrierea și apelarea unei proceduri. Opțiuni. Un exemplu de descriere a procedurii și apel. Tipuri de parametri. Program.

Un mecanism foarte important pentru aplicațiile client-server este furnizat de RPC ( Apel de procedură de la distanță). RPC a fost dezvoltat de Sun Micrsystems și este o colecție de instrumente și funcții de bibliotecă. În special, NIS (Network Information System) și NFS (Network File System) funcționează pe RPC.

Un server RPC constă dintr-un sistem de astfel de proceduri pe care un client le poate accesa prin trimiterea unei cereri RPC către server împreună cu parametrii procedurii. Serverul va apela procedura desemnată și va returna valoarea returnată a procedurii, dacă există. Pentru a fi independent de mașină, toate datele schimbate între client și server sunt convertite într-o așa-numită reprezentare a datelor externe ( Reprezentarea datelor externe, XDR). RPC comunică cu socket-urile UDP și TCP pentru a transfera date în format XDR. Sun a declarat RPC ca domeniu public, iar descrierea acestuia este disponibilă într-o serie de documente RFC.

Uneori, modificările aplicațiilor RPC introduc incompatibilitate în procedura de apelare a interfeței. Desigur, o simplă modificare ar face ca serverul să blocheze orice aplicație care încă așteaptă aceleași apeluri. Prin urmare, programele RPC au numere de versiune atribuite, de obicei începând cu 1. Fiecare versiune nouă a RPC ține evidența numărului de versiune. Adesea, serverul poate oferi mai multe versiuni în același timp. Clienții în acest caz specifică numărul versiunii pe care doresc să-l folosească.

Comunicarea în rețea între serverele RPC și clienți este puțin specială. Un server RPC oferă una sau mai multe proceduri de sistem, fiecare set de astfel de proceduri fiind numit program ( program) și este identificat în mod unic prin numărul programului ( numărul programului). O listă de nume de servicii este de obicei păstrată în /etc/rpc, un exemplu din care este dat mai jos.

Exemplul 12-4. Exemplu de fișier /etc/rpc

# # /etc/rpc - servicii diverse bazate pe RPC # portmapper 100000 portmap sunrpc rstatd 100001 rstat rstat_svc rup perfmeter rusersd 100002 rusers nfs 100003 nfsprog yp00 mount04 y1000 mount04 y1000 pbind 100007 walld 100008 rwall oprire yppasswdd 100009 yppasswd bootparam 100026 ypupdated 100028 ypupdate

În rețelele TCP/IP, autorii RPC s-au confruntat cu sarcina de a mapa numerele de programe cu serviciile comune de rețea. Fiecare server oferă un port TCP și UDP pentru fiecare program și fiecare versiune. În general, aplicațiile RPC folosesc UDP pentru a transmite date și revin la TCP atunci când datele de transmis nu se potrivesc într-o singură datagramă UDP.

Desigur, programele client trebuie să aibă o modalitate de a afla care port corespunde numărului de program. Utilizarea unui fișier de configurare pentru aceasta ar fi prea inflexibilă; Deoarece aplicațiile RPC nu folosesc porturi rezervate, nu există nicio garanție că portul nu este ocupat de anumite aplicații și este disponibil pentru noi. Prin urmare, aplicațiile RPC aleg orice port pe care îl pot primi și înregistrează demonul portmapper. Un client care dorește să contacteze un serviciu cu un anumit număr de program va face mai întâi o solicitare către portmapper pentru a afla numărul portului serviciului dorit.

Această metodă are dezavantajul că introduce un singur punct de eșec, la fel ca inetd demonul Cu toate acestea, acest caz este puțin mai rău, deoarece atunci când portmapper-ul eșuează, toate informațiile RPC despre porturi se pierd. Acest lucru înseamnă de obicei că trebuie să reporniți manual toate serverele RPC sau să reporniți mașina.

Pe Linux, portmapper-ul se numește /sbin/portmap sau /usr/sbin/rpc.portmap . În afară de faptul că trebuie lansat din scriptul de pornire a rețelei, portmapper nu necesită nicio muncă de configurare.

Remote Procedure Call RPC Conceptul de Remote Procedure Call Ideea din spatele Remote Procedure Call (RPC) este de a extinde mecanismul bine-cunoscut și înțeles pentru transferul de control și date într-un program care rulează pe o singură mașină pentru a transfera controlul și datele printr-o rețea. Instrumentele de apel de procedură la distanță sunt concepute pentru a facilita organizarea calculului distribuit.Cea mai mare eficiență a utilizării RPC este obținută în acele aplicații în care există comunicare interactivă între componentele de la distanță cu timpi de răspuns scurti și o cantitate relativ mică de date transferate.

Astfel de aplicații sunt numite RPC-oriented. Trăsăturile caracteristice ale procedurilor locale de apelare sunt Asimetria, adică una dintre părțile care interacționează este inițiatorul Sincronicitatea, adică executarea procedurii de apelare se oprește din momentul emiterii cererii și se reia numai după revenirea din procedura apelată. Implementarea apelurilor la distanță este mult mai complicată decât implementarea apelurilor către procedurile locale.

Pentru început, deoarece procedurile de apelare și apelare sunt executate pe mașini diferite, acestea au spații de adrese diferite, iar acest lucru creează probleme la transmiterea parametrilor și a rezultatelor, mai ales dacă mașinile nu sunt identice.Deoarece RPC nu se poate baza pe memoria partajată, aceasta înseamnă că parametrii RPC nu trebuie să conțină pointeri către locații de memorie care nu sunt stive și că valorile parametrilor ar trebui copiate de pe un computer pe altul.

Următoarea diferență între RPC și un apel local este că folosește neapărat sistemul de comunicare de bază, dar acest lucru nu ar trebui să fie vizibil în mod explicit nici în definirea procedurilor, nici în procedurile în sine. Depărtarea introduce probleme suplimentare. Execuția programului apelant și a procedurii locale apelate pe aceeași mașină este implementată în cadrul unui singur proces, dar implementarea RPC implică cel puțin două procese - câte unul în fiecare mașină.

În cazul în care una dintre ele se blochează, pot apărea următoarele situații: dacă procedura de apelare se blochează, procedurile apelate de la distanță vor deveni orfane, iar dacă procedurile de la distanță se blochează, procedurile de apelare vor deveni părinți orfani, care vor aștepta în zadar un răspuns. de la procedurile de la distanță. În plus, există o serie de probleme asociate cu eterogenitatea limbajelor de programare și a mediilor de operare, structurile de date și structurile de apel de procedură acceptate în niciun limbaj de programare nu sunt acceptate în același mod în toate celelalte limbi.

Acestea și alte probleme sunt rezolvate de tehnologia RPC răspândită, care stă la baza multor sisteme de operare distribuite. Operații RPC de bază Pentru a înțelege cum funcționează RPC, să luăm în considerare mai întâi efectuarea unui apel de procedură locală pe o mașină obișnuită care rulează autonom. Să fie, de exemplu, numărul apelurilor de sistem read fd,buf,nbytes unde fd este un număr întreg, buf este o matrice de caractere, nbytes este un număr întreg.

Pentru a efectua apelul, procedura de apelare împinge parametrii pe stivă în ordinea inversă a Figura 3.1. După ce apelul de citire este executat, plasează valoarea returnată într-un registru, mută adresa de retur și readuce controlul la procedura de apelare, care scoate parametrii din stivă, revenind la starea inițială. Rețineți că în C, parametrii poate fi apelat prin referință sau după nume sau după valoare. În raport cu procedura apelată, parametrii de valoare sunt variabile locale inițializate.

Procedura apelată le poate modifica fără a afecta valorile inițiale ale acestor variabile în procedura de apelare. Dacă un pointer către o variabilă este transmis procedurii apelate, atunci schimbarea valorii acestei variabile de către procedura apelată implică modificarea valorii acestei variabile pentru procedura apelată.Acest fapt este foarte semnificativ pentru RPC. Există, de asemenea, un alt mecanism de transmitere a parametrilor care nu este folosit în C. Se numește restaurare call-by-copy și implică ca programul apelant să copieze variabilele în stivă ca valori, iar apoi să le copieze înapoi după ce apelul este efectuat peste originalul. valorile procedurii de apelare.

Decizia despre ce mecanism de trecere a parametrilor să fie utilizat este luată de dezvoltatorii limbajului. Uneori, acest lucru depinde de tipul de date transmise. În C, de exemplu, numerele întregi și alte date scalare sunt întotdeauna transmise după valoare, iar tablourile sunt întotdeauna transmise prin referință.

Orez. 3.1. a Stiva înainte de executarea apelului de citire b Stiva în timpul execuției procedurii c Stiva după revenirea la programul apelant Ideea din spatele RPC este de a face ca un apel către o procedură de la distanță să arate cât mai asemănător cu un apel către un procedura locala. Cu alte cuvinte, pentru a face RPC transparent, procedura de apelare nu trebuie să știe că procedura apelată este pe o altă mașină și invers. RPC realizează transparență în felul următor.

Când procedura apelată este de fapt la distanță, în loc de procedura locală, o altă versiune a procedurii, numită client stub, este plasată în bibliotecă. Similar cu procedura inițială, stub-ul este apelat folosind secvența de apelare ca în Figura 3.1 și apare o întrerupere la accesarea nucleului. Numai că, spre deosebire de procedura inițială, nu plasează parametri în registre și nu solicită date de la kernel; în schimb, generează un mesaj care urmează să fie trimis către nucleul mașinii la distanță. Etapele execuției RPC Interacțiunea componentelor software la efectuarea unui apel de procedură la distanță este ilustrată în Figura 3.2. După ce stub-ul clientului a fost apelat de către programul client, prima sa sarcină este să umple buffer-ul cu mesajul trimis.

În unele sisteme, stub-ul clientului are un singur buffer cu lungime fixă ​​care este umplut de la bun început cu fiecare cerere nouă. În alte sisteme, buffer-ul de mesaje este un grup de buffere pentru câmpurile individuale de mesaje, dintre care unele sunt deja pline.

Această metodă este potrivită în special pentru cazurile în care pachetul are un format format dintr-un număr mare de câmpuri, dar valorile multora dintre aceste câmpuri nu se schimbă de la apel la apel. Parametrii trebuie apoi convertiți în formatul corespunzător și inserați în buffer-ul de mesaje.În acest moment, mesajul este gata pentru a fi trimis, astfel încât întreruperea apelului nucleului este executată. Orez. 3.2. Apel de procedură de la distanță Când nucleul câștigă controlul, schimbă contextele, salvează registrele procesorului și mânerele paginii hărți de memorie și instalează o nouă hartă de memorie care va fi folosită pentru a rula în modul kernel. Deoarece nucleul și contextele utilizatorului sunt diferite, nucleul trebuie să copieze mesajul exact în propriul spațiu de adrese, astfel încât să-l poată accesa, să-și amintească adresa de destinație și eventual alte câmpuri de antet și trebuie să-l transmită interfeței de rețea.

Acest lucru completează munca din partea clientului.

Cronometrul de transmisie este pornit, iar nucleul poate fie să interogheze ciclic pentru un răspuns, fie să transmită controlul către planificator, care va selecta un alt proces de rulat. În primul caz, execuția interogării este accelerată, dar multiprogramarea este absentă. Pe partea de server, biții de intrare sunt plasați de hardware-ul receptor fie în buffer-ul încorporat, fie în RAM.Când toate informațiile au fost recepționate, este generată o întrerupere.

Managerul de întrerupere verifică datele pachetului pentru valabilitate și determină cărui stub să-l transmită. Dacă niciun stub nu așteaptă pachetul, handler-ul de întrerupere trebuie fie să-l tamponeze, fie să-l renunțe complet. Dacă există un talon în așteptare, mesajul este copiat pe acesta. În final, se efectuează o comutare de context, în urma căreia se restabilesc registrele și harta memoriei, luând valorile pe care le aveau în momentul în care stub-ul a efectuat apelul de recepție.

Acum, ștuțul serverului începe să funcționeze. Dezambalează parametrii și îi împinge în mod corespunzător pe stivă. Când totul este gata, se efectuează un apel către server. După finalizarea procedurii, serverul transmite rezultatele către client.Pentru a face acest lucru, toți pașii descriși mai sus sunt executați, doar în ordine inversă. Figura 3.3 arată secvența comenzilor care trebuie executate pentru fiecare apel RPC, iar Figura 3.4 arată ce proporție din timpul total de execuție RPC este cheltuită pentru fiecare dintre cei 14 pași descriși.

Testele au fost efectuate pe o stație de lucru cu mai multe procesoare DEC Firefly și, în timp ce prezența a cinci procesoare a afectat în mod necesar rezultatele măsurătorilor, histograma prezentată în figură oferă o idee generală a procesului de execuție RPC. Orez. 3.3. Etapele procedurii RPC Fig. 3.4. Distribuția timpului între 14 etape ale execuției RPC 1. Apelarea unui stub 2. Pregătirea unui buffer 3. Parametrii pachetului 4. Completați câmpul antet 5. Calculați suma de control din mesaj 6. Întreruperea nucleului 7. Puneți pachetul în coadă pentru execuție 8. Transferați mesajul către controler prin intermediul magistralei QBUS 9. Timp de transfer prin rețeaua Ethernet 10. Primirea unui pachet de la controler 11. Procedura de gestionare a întreruperilor 12. Calculul sumei de control 13. Comutarea contextului în spațiul utilizator 14. Efectuarea unui stub de server Legarea dinamică Să luăm în considerare întrebarea cum specifică clientul locația serverului.

O metodă de a rezolva această problemă este utilizarea directă a adresei de rețea a serverului în programul client.

Dezavantajul acestei abordări este că este extrem de inflexibilă la mutarea serverului, la creșterea numărului de servere sau la schimbarea interfeței; în toate acestea și în multe alte cazuri, este necesar să se recompileze toate programele care au folosit setarea hard a serverului. Pentru a evita toate aceste probleme, în Unele sisteme distribuite folosesc ceea ce se numește legături dinamice.

Punctul de plecare pentru legarea dinamică este definirea formală a specificației serverului. Specificația conține numele serverului de fișiere, numărul versiunii și o listă de proceduri de service furnizate de acest server clienților (Figura 3.5). Pentru fiecare procedură este dată o descriere a parametrilor săi, indicând dacă acest parametru este de intrare sau de ieșire în raport cu serverul.Unii parametri pot fi atât de intrare cât și de ieșire - de exemplu, o matrice care este trimisă de client către server este modificată acolo și apoi a revenit la operațiunea client copiere restaurare . Orez. 3.5. Specificația serverului RPC Specificația serverului formal este utilizată ca intrare în programul generator de stub, care creează atât stub-uri client, cât și server.

Acestea sunt apoi plasate în bibliotecile corespunzătoare. Când un program client utilizator apelează orice procedură definită în specificația serverului, procedura stub corespunzătoare este asociată cu codul binar al programului.

De asemenea, atunci când un server este compilat, cioturile de server sunt asociate cu acesta. Când serverul pornește, prima sa acțiune este să-și transfere interfața serverului într-un program special numit binder. Acest proces, cunoscut sub numele de proces de înregistrare a serverului, implică transmiterea de către server a numelui său, a numărului versiunii, a identificatorului unic și a unui descriptor al locației serverului. Descriptorul este independent de sistem și poate fi un IP, Ethernet, X.500 sau ceva altă adresă.

În plus, poate conține și alte informații, de exemplu legate de autentificare. Când un client apelează una dintre procedurile de la distanță pentru prima dată, de exemplu, citire, stub-ul clientului vede că nu este încă conectat la server și trimite un mesaj programului de legătură cu o solicitare de importare a interfeței versiunea dorită a serverului dorit. Dacă un astfel de server există, atunci Binder trimite descriptorul și identificatorul unic pentru stub-ul clientului.

Când trimiteți un mesaj cu o solicitare, stub-ul clientului folosește un descriptor ca adresă. Mesajul conține parametri și un identificator unic pe care nucleul serverului îl folosește pentru a direcționa mesajul primit către serverul dorit, dacă există mai mulți dintre aceștia pe această mașină. Această metodă de import și export de interfețe este foarte flexibilă. De exemplu, pot exista mai multe servere care acceptă aceeași interfață, iar clienții sunt distribuiți aleatoriu între servere.

În cadrul acestei metode, devine posibilă interogarea periodică a serverelor, analizarea performanței acestora și, în caz de defecțiune, oprirea automată, ceea ce crește toleranța generală la erori a sistemului. Această metodă poate suporta și autentificarea clientului. De exemplu, serverul poate determina că poate fi folosit doar de clienți dintr-o anumită listă. Cu toate acestea, legarea dinamică are dezavantaje, cum ar fi supraîncărcarea suplimentară și timpul petrecut exportând și importând interfețe.

Amploarea acestor costuri poate fi semnificativă, deoarece multe procese client există pentru o perioadă scurtă de timp, iar de fiecare dată când procesul începe, procedura de import a interfeței trebuie efectuată din nou. În plus, în sistemele mari distribuite, programul de liant poate deveni un blocaj, iar crearea mai multor programe cu același scop crește, de asemenea, supraîncărcarea de creare și sincronizare a proceselor.Semantica RPC în caz de defecțiuni În mod ideal, RPC ar trebui să funcționeze corect în cazul a eșecurilor.

Luați în considerare următoarele clase de eșec: 1. Clientul nu poate localiza serverul, de exemplu, dacă serverul dorit eșuează sau pentru că programul client a fost compilat cu mult timp în urmă și a folosit o versiune veche a interfeței serverului. În acest caz, ca răspuns la solicitarea clientului, se primește un mesaj care conține un cod de eroare. 2. Solicitarea de la client catre server a fost pierduta.Cea mai simpla solutie este repetarea cererii dupa un anumit timp. 3. Mesajul de răspuns de la server către client este pierdut.

Această opțiune este mai complicată decât cea anterioară, deoarece unele proceduri nu sunt idempotente. O procedură idempotentă este o procedură a cărei cerere de execuție poate fi repetată de mai multe ori fără a modifica rezultatul. Un exemplu de astfel de procedură este citirea unui fișier, dar procedura de retragere a unei anumite sume dintr-un cont bancar nu este idempotentă, iar dacă răspunsul se pierde, o solicitare repetată poate schimba semnificativ starea contului clientului.

O soluție posibilă este de a face toate procedurile idempotente. Cu toate acestea, în practică acest lucru nu este întotdeauna posibil, așa că poate fi folosită o altă metodă - numerotarea secvențială a tuturor solicitărilor de către nucleul clientului. Nucleul serverului își amintește numărul celei mai recente solicitări de la fiecare client și, la primirea fiecărei cereri, analizează dacă această solicitare este primară sau repetată. 4. Serverul s-a prăbușit după ce a primit cererea. Proprietatea idempotity este și ea importantă aici, dar din păcate abordarea cu numerotarea cererii nu poate fi aplicată.

În acest caz, contează când a avut loc defecțiunea - înainte sau după operație. Dar nucleul clientului nu poate recunoaște aceste situații; știe doar că timpul de răspuns a expirat. Există trei abordări ale acestei probleme: Așteptați până când serverul repornește și încercați din nou operațiunea Această abordare asigură că RPC-ul este finalizat cel puțin o dată și, eventual, mai multe. Raportați imediat eroarea către aplicație.

Această abordare asigură că RPC este executat cel mult o dată. A treia abordare nu garantează nimic. Când serverul eșuează, clientului nu i se oferă suport. RPC poate fie să nu fie executat deloc, fie poate fi executat de mai multe ori. În orice caz, această metodă este foarte ușor de implementat. Niciuna dintre aceste abordări nu este foarte atractivă, iar opțiunea ideală, care ar garanta exact o execuție RPC, în cazul general nu poate fi implementată din motive de principiu.

Să fie, de exemplu, o operațiune de la distanță să fie tipărirea unui text, care include încărcarea buffer-ului imprimantei și setarea unui bit într-un registru de control al imprimantei, în urma căruia imprimanta pornește. O blocare a serverului poate avea loc fie cu o microsecundă înainte, fie cu o microsecundă. după ce bitul de control este setat. Momentul eșecului determină în întregime procedura de recuperare, dar clientul nu poate afla despre momentul eșecului.

Pe scurt, posibilitatea unui accident de server schimbă radical natura RPC și reflectă în mod clar diferența dintre un sistem centralizat și unul distribuit. În primul caz, o blocare a serverului duce la o blocare a clientului, iar recuperarea este imposibilă. În al doilea caz, este posibil și necesar să se efectueze acțiuni de recuperare a sistemului. 1. Clientul s-a blocat după trimiterea cererii. În acest caz, calculele sunt efectuate pe rezultate la care nimeni nu se așteaptă. Astfel de calcule se numesc calcule orfane. Prezența orfanilor poate cauza diverse probleme: supraîncărcarea timpului CPU, blocarea resurselor, înlocuirea răspunsului la cererea curentă cu un răspuns la o solicitare care a fost emisă de mașina client înainte ca sistemul să fie repornit.

Cum să te descurci cu orfanii? Să ne uităm la 4 soluții posibile. Distrugere. Înainte ca stub-ul clientului să trimită un mesaj RPC, acesta face o notă în jurnal indicând ce va face în continuare. Jurnalul este stocat pe disc sau altă memorie tolerantă la erori.

După accident, sistemul este repornit, jurnalul este analizat și orfanii sunt eliminați. Dezavantajele acestei abordări includ, în primul rând, supraîncărcarea crescută asociată cu scrierea fiecărui RPC pe disc și, în al doilea rând, posibila ineficiență din cauza apariției orfanilor din a doua generație generate de apelurile RPC emise de orfanii din prima generație. Reîncarnarea În acest caz, toate problemele sunt rezolvate fără a utiliza înregistrarea pe disc. Metoda constă în împărțirea timpului în perioade numerotate secvenţial. Când clientul repornește, acesta transmite un mesaj către toate mașinile pentru a anunța începutul unei noi perioade.

După primirea acestui mesaj, toate calculele de la distanță sunt eliminate. Desigur, dacă rețeaua este segmentată, atunci unii orfani pot supraviețui. Reîncarnarea soft este similară cu cazul precedent, cu excepția faptului că nu toate calculele șterse sunt găsite și distruse, ci doar calculele clientului de repornire. Expirare.Fiecărei cereri i se acordă o perioadă standard de timp T în care trebuie finalizată.

Dacă cererea nu este finalizată în timpul alocat, se alocă un cuantum suplimentar. Deși acest lucru necesită muncă suplimentară, dacă după un accident de client, serverul așteaptă un interval T înainte de a reporni clientul, atunci toți orfanii sunt în mod necesar distruși. În practică, niciuna dintre aceste abordări nu este de dorit; de fapt, distrugerea orfanilor poate înrăutăți situația. . De exemplu, să presupunem că un orfan a blocat unul sau mai multe fișiere de bază de date.

Dacă orfanul este distrus brusc, atunci aceste încuietori vor rămâne, în plus, orfanii distruși pot rămâne în picioare în diferite cozi de sistem, în viitor pot provoca execuția de noi procese etc.

Ce vom face cu materialul primit:

Dacă acest material ți-a fost util, îl poți salva pe pagina ta de pe rețelele sociale:

Ideea de a apela proceduri de la distanță (Apel de procedură de la distanță - RPC) constă în extinderea mecanismului bine-cunoscut și înțeles de transfer de control și date în cadrul unui program care rulează pe o mașină la transferul de control și date printr-o rețea. Instrumentele de apelare a procedurilor de la distanță sunt concepute pentru a facilita organizarea calculului distribuit.

Cea mai mare eficiență a utilizării RPC se realizează în acele aplicații în care există comunicare interactivă între componentele de la distanță Cu timp scurt de răspunsȘi cantitate relativ mică de date transmise.Astfel de aplicații sunt numite RPC-oriented.

Trăsăturile caracteristice ale apelării procedurilor locale sunt:

    asimetrie, adică una dintre părțile care interacționează este inițiatorul;

    sincronicitate, adică executarea procedurii de apelare se suspendă din momentul emiterii cererii și se reia numai la revenirea procedurii apelate.

Implementarea apelurilor de la distanță este mult mai complicată decât implementarea apelurilor de procedură locală.

1. Să începem cu faptul că, deoarece procedurile de apelare și apelare sunt executate pe mașini diferite, acestea au spații de adrese diferite, iar asta creează probleme la transferul parametrilor și rezultatelor, mai ales dacă mașinile nu sunt identice.

Deoarece RPC nu se poate baza pe memoria partajată, aceasta înseamnă că Parametrii RPC nu trebuie să conțină pointeri către locații de memorie non-stivăŞi ce dacă valorile parametrilor trebuie copiate de pe un computer pe altul.

2. Următoarea diferență între RPC și un apel local este că acesta folosește în mod necesar sistemul de comunicare subiacent, cu toate acestea, aceasta nu trebuie să fie clar vizibile nici în definirea procedurilor, nici în procedurile în sine .

Depărtarea introduce probleme suplimentare. Executarea programului de apelare și a procedurii locale apelate pe aceeași mașină implementate în cadrulsingur proces. Dar implicate în implementarea RPCcel puțin două procese - câte unul în fiecare mașină. Dacă una dintre ele eșuează, pot apărea următoarele situații:

    Dacă procedura de apelare se blochează, procedurile apelate de la distanță vor deveni „orfane” și

    Dacă procedurile de la distanță se încheie în mod anormal, procedurile de apelare vor deveni „părinți săraci” și vor aștepta un răspuns de la procedurile de la distanță fără niciun rezultat.

În plus, există o serie de probleme asociate cu eterogenitatea limbajelor de programare și a mediilor de operare : Structurile de date și structurile de apel de procedură acceptate în orice limbaj de programare nu sunt acceptate în același mod în toate celelalte limbaje.

Acestea și alte probleme sunt rezolvate de tehnologia RPC răspândită, care stă la baza multor sisteme de operare distribuite.

Ideea din spatele RPC este de a face un apel de procedură la distanță să arate cât mai asemănător cu un apel de procedură locală. Cu alte cuvinte, faceți RPC transparent: procedura de apelare nu trebuie să știe că procedura apelată este pe o altă mașină și invers.

RPC realizează transparență în felul următor. Când procedura apelată este de fapt la distanță, o altă versiune a procedurii, numită client stub, este plasată în bibliotecă în locul procedurii locale. La fel ca procedura originală, stub-ul este apelat folosind o secvență de apelare (ca în Figura 3.1) și apare o întrerupere la accesarea nucleului. Numai că, spre deosebire de procedura inițială, nu plasează parametri în registre și nu solicită date de la kernel; în schimb, generează un mesaj pentru a fi trimis către nucleul mașinii la distanță..

Orez. 3.2. Apel de procedură de la distanță