Explorați Cărți electronice
Categorii
Explorați Cărți audio
Categorii
Explorați Reviste
Categorii
Explorați Documente
Categorii
COMUNICAII INTER-PROCESE
Mecanismele de comunicare ntre procese permit acestora s schimbe date ntre ele i
s-i sincronizeze execuia. Au fost prezentate deja cteva modaliti de comunicare
ntre procese, cum ar fi pipe-urile (nenumite), pipe-urile numite i semnalele. Pipeurile (nenumite) au dezavantajul c sunt cunoscute numai de ctre procesele care
sunt fii ai procesului care a invocat apelul sistem pipe. Procesele nenrudite (ntre care
nu exista o relaie de tip tat-fiu-nepot-...) nu pot comunica prin pipe-uri. Dei pipeurile numite permit comunicarea ntre procese nenrudite, ele nu reprezint totui o
modalitate de comunicare n reea (vezi Cap.13) i nici nu pot fi uor adaptate pentru
folosirea cilor multiple de comunicare ntre grupuri diferite de procese care comunic:
este imposibil multiplexarea unui pipe numit pentru a pune la dispoziie canale
separate perechilor de procese care comunic. De asemenea, procesele oarecare mai
pot comunica i prin trimiterea de semnale unul altuia, cu ajutorul apelului sistem kill,
dar n acest caz mesajul const doar ntr-un numr asociat semnalului.
n acest capitol se descriu alte forme de comunicare ntre procese. Capitolul ncepe
prin studierea execuiei pas cu pas a proceselor, nelegnd prin aceasta faptul c un
proces urmrete i controleaz execuia pas cu pas a altui proces, iar apoi continu
cu explicarea modalitilor de comunicare ntre procese, modaliti specifice variantei
System V i cunoscute sub numele System V IPC: comunicarea prin mesaje, prin
memorie comun (partajat) i prin semafoare. Se face o trecere n revist a
metodelor obinuite prin care se realizeaz comunicarea ntre procese de pe maini
diferite prin intermediul unei reele i, n final, se face o prezentare la nivel utilizator a
socket-urilor BSD. Nu se iau n discuie probleme specifice reelelor, cum ar fi
protocoale i adrese, acestea nefcnd obiectul de studiu al crii.
10.1.
248
if((pid=fork())==0)
{
/* proces fiu=procesul studiat */
ptrace(0,0,0,0);
exec(numele procesului studiat);
}
/* aici continua procesul tat=proccesul depanator */
for(;;)
{
wait((int *)0);
read(intrri pentru instruciuni de execuie pas cu pas);
ptrace(cmd,pid,...);
if(condiie de ieire din execuia pas cu pas)
break;
}
Figura 10.1. Structura unui proces de depanare.
Pseudocodul din figura 3.1. pune in eviden o structur caracteristic pentru un
program de depanare. Procesul .depanator creaz un proces fiu, care invoc apelul
sistem ptrace al crui rezultat este poziionarea pe 1 a bitului de execuie pas cu pas
n intrarea corespunztoare procesului fiu, din tabela de procese (Process Table).
Procesul fiu execut, prin apelul sistem exec, programul care urmeaz a fi .depanat.
De exemplu, dac utilizatorul dorete s depaneze programul a.out , atunci
argumentul transmis apelului sistem exec va fi irul de caractere a.out i procesul fiu
va executa acest program. Nucleul va executa apelul sistem exec ca de obicei, dar la
sfrit va observa faptul c bitul de execuie pas cu pas este poziionat pe 1 i, n
consecin va trimite procesului fiu un semnal .trap. La ntoarcerea din apelul sistem
exec, nucleul verific dac s-au trimis semnale -aa cum o face, de altfel, la
ntoarcerea din orice alt apel sistem- gsete semnalul trap pe care, chiar el, tocmai
l-a trimis i execut pas cu pas codul procesului fiu, ntocmai ca pe o secven
special de tratare a semnalelor. Observnd poziionarea pe 1 a bitului de execuie pas
cu pas din propria intrare n tabela de procese, procesul fiu trezete procesul printe
din starea de ateptare instituit n urma apelului sistem wait (dup cum se va vedea
mai trziu), intr ntr-o stare special (stare trace-de execuie pas cu pas, care nu
este evideniat n diagrama strilor proceselor) asemntoare strii sleep i face o
comutare de context.
n mod obinuit, procesul printe (depanatorul) va fi intrat deja intr-un ciclu,
ateptnd s fie trezit din starea de sleep (instituit de apelul sistem wait ) de ctre
procesul fiu (adic procesul executat pas cu pas). Cnd procesul fiu trezete procesul
printe, acesta ncheie execuia apelului sistem wait, citete comenzile de la intrare ale
utilizatorului prin apelul read i le convertete intr-o serie de apeluri ptrace n scopul
controlrii execuiei procesului fiu.
Sintaxa apelului sistem ptrace este urmtoarea:
-unde cmd specific diverse comenzi cum ar fi citirea sau scrierea datelor, ori reluarea
execuiei i alte comenzi, pid reprezint identificatorul de proces al procesului care se
execut pas cu pas, addr reprezint adresa virtual, din cadrul procesului fiu, la (de la)
care se va scrie (citi) i data reprezint o valoare de tip ntreg care se va scrie. La
249
executarea apelului sistem ptrace, nucleul verific dac procesul depanator are
vreun proces fiu al crui identificator este egal cu valoarea parametrului pid i dac
acest proces fiu se afl n starea trace, utiliznd apoi o structur de date global,
dedicat execuiei pas cu pas, pentru realizarea transferului de date ntre cele dou
procese. Nucleul blocheaz accesul la structura de date global amintit, pentru a
mpiedica scrierea de ctre alte procese aflate n execuie pas cu pas, copiaz valorile
parametrilor cmd, addr i data n structura de date, trezete procesul fiu i-l trece n
starea ready-to-run, punndu-se apoi n ateptare pn la sosirea rspunsului de la
procesul fiu. Cnd procesul fiu i reia execuia (n modul nucleu), el execut comanda
prevzut n parametrul cmd, scrie rezultatul executrii comenzii n structura de date
global dedicat execuiei pas cu pas i apoi trezete procesul depanator. n funcie
de comanda precizat prin parametrul cmd, procesul fiu poate s reintre n starea
trace ateptnd o nou comand, sau poate ncheia tratarea semnalului relundu-i
execuia. Cnd procesul depanator i reia execuia, nucleul memoreaz valoarea de
retur furnizat de procesul executat pas cu pas, deblocheaz accesul la structura de
date global corespunztoare i red controlul utilizatorului.
Dac, n momentul intrrii procesului fiu n starea trace, procesul depanator nu se
afl n starea sleep (ca efect al apelului sistem wait), el nu va putea determina care
este procesul fiu ce se va executa pas cu pas, dect n momentul invocrii apelului
sistem wait, moment n care se va ntoarce imediat i va proceda aa cum tocmai a
fost descris mai sus.
int data[32];
main()
{
int I;
for(i=0;i<32;i++)
printf(data[%d]=%d\n,i,data[i]);
printf(ptrace data addr 0x%x\n,data);
}
Figura 10.2. Programul trace -- un proces executat pas cu pas
pas, din coninutul creia determin adresele utilizate ca parametri pentru apelurile
procedurii ptrace.
Utilizarea apelului sistem ptrace n scopul executrii pas cu pas a proceselor, este o
metod rudimentar care prezint mai multe dezavantaje.
Nucleul trebuie s execute patru comutri de context, pentru a realiza transferul unui
octet de date ntre procesul depanator i procesul executat pas cu pas, astfel:-o
comutare de context n cadrul procesului depanator la invocarea apelului sistem
ptrace, pn cnd procesul executat pas cu pas trimite un rspuns;-dou comutri de
context la intrarea n -i la ieirea din- procesul executat pas cu pas; -o comutare de
context napoi ctre procesul depanator mpreun cu rspunsul ctre apelul ptrace.
Aceast penalizare este necesar, ntruct un proces depanator nu are alt
modalitate de a accesa spaiul virtual de adrese al procesului executat pas cu pas, n
consecin execuia pas cu pas este consumatoare de timp.
Un proces depanator poate executa pas cu pas mai multe procese fii simultan, cu
toate c, n practic, aceast facilitate este rareori exploatat. Un aspect mai critic l
reprezint, ns, faptul c un proces depanator nu poate executa pas cu pas dect
procese fii, adic: -dac un proces fiu, executat pas cu pas, invoc apelul sistem fork
(adic i creaz propriul proces fiu), atunci procesul depanator nu are nici un control
asupra procesului nepot, ceea ce reprezint o restricie major n cazul depanrii
programelor complexe. Dac un proces executat pas cu pas invoc apelul sistem exec,
depanarea se continu i la nivelul imaginilor -ulterioare apelului exec - ale procesului
depanat, din cauza apelului ptrace primar, depanatorul neputnd, ns, s tie
numele imaginii procesului care a rezultat n urma apelului exec, ceea ce face dificil
depanarea simbolic.
Un proces depanator nu poate executa pas cu pas un alt proces care se afl deja n
execuie, dac acesta din urm nu a invocat, n prealabil, apelul sistem ptrace , pentru
a preveni nucleul asupra faptului c permite execuia sa, pas cu pas. Acest lucru
este, de asemenea, un dezavantaj, deoarece pentru a executa pas cu pas un anumit
proces aflat deja n execuie, atunci acesta trebuie n prealabil terminat (cu apelul
kill) i relansat n execuie, n modul trace.
Nu este posibil execuia pas cu pas a programelor care au poziionat pe 1 bitul
setuid, deoarece utilizatorii ar putea nclca drepturile de acces, avnd posibilitatea de
a scrie n spaiul virtual de adrese al acestor programe, cu ajutorul apelului sistem
ptrace, i de a executa operaiuni nepermise prin drepturile de acces. De exemplu, s
presupunem c un astfel de program, invoc apelul exec avnd ca parametru numele
de fiier privatefile. Un utilizator iste s-ar putea folosi de apelul sistem ptrace pentru
a modifica parametrul respectiv la valoarea /bin/sh, lansnd astfel n execuie shell-ul
(cu toate programele asociate acestuia) fr a avea permisiunea de a o face. Apelul
exec ignor valoarea bitului setuid dac procesul este executat pas cu pas, pentru a
evita scrierea de ctre un utilizator n cadrul spaiului de adrese a unui astfel de
program.
Killian [Killian 84] descrie o alt modalitate de execuie pas cu pas a proceselor, bazat
pe lucrul cu sistemele de fiiere, descris n capitolul .... . Administratorul de sistem
monteaz un sistem de fiiere, /proc; -utilizatorii identific procesele pe baza PID-ului
acestora i le trateaz ca fiind fiiere din /proc. Nucleul acord permisiunea de
deschidere a fiierelor (cu apelul sistem open), n conformitate cu identificatorii UID i
GID. Utilizatorii au posibilitatea de a accesa spaiul de adrese pentru citire (prin
apelul read) i de a stabili puncte de ntrerupere (breakpoints) prin scriere n fiier (cu
apelul write). Apelul stat furnizeaz diverse informaii de ordin statistic despre
procese. Aceast metod nltur trei dintre dezavantajele utilizrii apelului ptrace.
251
Mai nti, aceast metod este mai rapid deoarece un proces depanator poate
transfera o cantitate mai mare de date la un apel sistem, n comparaie cu apelul
ptrace. n al doilea rnd, un proces depanator poate executa pas cu pas orice
proces, care nu trebuie s fie neaprat un proces fiu al su. n sfrit, un proces
depanat nu necesit msuri prealabile pentru a permite execuia sa pas cu pas; -un
proces depanator poate executa pas cu pas procese deja n curs de execuie. Ca
parte a mecanismului obinuit de protecie a fiierelor, apare faptul c doar superuserul poate executa pas cu pas procesele care au setat bitul setuid pentru fiierele din
rdcin.
10.2.
Pachetul System V IPC din UNIX se compune din trei mecanisme. Mesajele permit
proceselor s trimit fluxuri de date formatate ctre alte procese, memoria comun
permite proceselor s foloseasc n comun pri din spaiul lor virtual de adrese, iar
semafoarele permit proceselor s-i sincronizeze execuia. Implementate n mod
unitar, aceste mecanisme au o serie de proprieti comune:
Fiecare mecanism conine o tabel ale crei intrri descriu toate instanele acelui
mecanism.
Fiecare intrare din tabel conine o cheie numeric (key), care reprezint numele su
desemnat de utilizator.
Fiecare mecanism dispune de un apel sistem de tip get destinat crerii unei noi
intrri, sau obinerii uneia deja existente, parametrii acestor apeluri incluznd o cheie
(key) i un indicator (flag). Nucleul caut n tabela corespunztoare intrarea
desemnat de ctre cheie. Procesele pot invoca apelurile de tip get cu parametrul
cheie avnd valoarea IPC_PRIVATE, pentru a se asigura de obinerea unei intrri
nefolosite. Procesele pot poziiona valoarea bitului IPC_CREAT din cadrul indicatorului
(flag-ului) pentru a crea o nou intrare, dac cea precizat prin cheie nu exist deja, i
de asemenea pot determina semnalizarea erorilor prin poziionarea indicatorilor
IPC_EXCL i IPC_CREAT, pentru situaia n care deja exist o intrare desemnat prin
acea cheie. Apelurile sistem de tip getreturneaz un descriptor determinat de nucleu,
care va fi ulterior utilizat ca parametru al altor apeluri sistem, rezultnd de aici
analogia cu apelurile sistem creat i open.
n cadrul fiecrui mecanism IPC (de comunicare ntre procese), pentru determinarea
indexului din tabela structurilor de date, nucleul utilizeaz urmtoarea formul bazat
pe valoarea descriptorului :
De exemplu, dac tabela structurilor de date pentru mesaje conine 100 de intrri,
atunci descriptorii pentru intrarea 1 sunt 1, 101, 201 .a.m.d. Cnd un proces
elibereaz o intrare, nucleul crete valoarea descriptorului asociat acesteia cu o
valoare egal cu numrul de intrri din tabel. Noua valoare, astfel obinut, devine
252
noul descriptor al intrrii respective, n cazul unei noi alocri a acesteia printr-un apel
de tip get. Orice ncercare ulterioar a proceselor de a accesa intrarea respectiv, pe
baza vechiului descriptor, se va solda cu eroare. n legtur cu exemplul de mai sus,
dac descriptorul asociat intrrii 1 din tabela pentru mesaje este 201, atunci cnd
intrarea respectiv este eliberat, nucleul i atribuie acesteia un nou descriptor, 301.
Procesele care ncearc s acceseze intrarea, pe baza vechiului descriptor (201), vor
primi un mesaj de eroare, deoarece acest descriptor nu mai este valabil. Nucleul
recicleaz eventual nnumerele pentru descriptori, probabil dup o lung perioad de
timp.
Fiecare intrare IPC dispune de o structur de date pentru stocarea permisiunilor,
aceasta incluznd indicatorul de utilizator i indicatorul de grup ale procesului care a
creat intrarea, un indicator de utilizator i unul de grup fixai printr-un apel sistem de
tip control i un set de permisiuni de citire-scriere-execuie (read-write-execute)
separat pentru utilizator, grup i ceilali (user, group, others), similare permisiunilor de
acces la fiiere.
Fiecare intrare conine i alte informaii de stare, cum ar fi PID-ul ultimului proces
care a actualizat intrarea (a trimis ori a primit un mesaj, a ataat o zon comun de
memorie .a.m.d.), precum i momentul ultimului acces sau al ultimei actualizri a
intrrii.
Fiecare mecanism dispune de un apel sistem de tip control prin care se primesc
informaii despre starea unei intrri, se seteaz starea unei intrri, sau se elibereaz o
intrare. Cnd un proces solicit informaii despre starea unei intrri, nucleul verific
dac acesta are drept de citire i apoi copiaz datele din intrare la adresa specificat
de utilizator. n mod similar, pentru modificarea valorilor dintr-o intrare, nucleul
verific dac UID-ul procesului corespunde cu UID-ul utilizatorului, sau cu UID-ul celui
care a creat intrarea, sau dac procesul n cauz este executat de ctre superuser;
dreptul de scriere nu este suficient pentru a se permite modificarea parametrilor unei
intrri. Nucleul copiaz datele precizate de ctre utilizator n intrarea din tabel,
setnd valorile UID-ului, GID-ului, permisiunile de acces, precum i coninutul altor
cmpuri, n funcie de tipul mecanismului de comunicare. Nucleul nu modific valorile
UID-ului i GID-ului aparinnd celui care a creat intrarea, astfel nct utilizatorul care
a creat intrarea respectiv i pstreaz drepturile de control asupra acesteia. n
sfrit, un utilizator poate elibera o intrare din tabel, dac este superuser, sau dac
PID-ul procesului su corespunde celui din structura de date a intrrii. Nucleul crete
numrul de descriptor asociat intrrii, astfel nct, la urmtoarea alocare a intrrii
respective, va returna un alt descriptor. Din acest motiv, aa cum s-a explicat mai sus,
apelurile sistem vor ntoarce un mesaj de eroare, dac un proces va ncerca s
acceseze o intrare utiliznd unul din vechii descriptori.
Exist patru apeluri sistem pentru comunicarea prin mesaje: msgget ntoarce (sau
creaz) un descriptor de mesaje, care desemneaz o coad de mesaje, utilizat ca
parametru n celelalte apeluri sistem; msgctl dispune de opiuni de setare sau
returnare a valorilor parametrilor asociai unui descriptor de mesaje, precum i de o
opiune de eliberare a descriptorilor; msgsnd trimite un mesaj, iar msgrcv
recepioneaz un mesaj.
253
unde msgqid este descriptorul returnat de apelul sistem, iar key i flag au
semnificaiile descrise mai sus, n cazul general al apelurilor de tip get. Nucleul
memoreaz mesajele sub forma unei liste nlnuite (queue - coad de mesaje) creia
i corespunde un descriptor, i folosete un descriptor de coad de mesaje -msgqid- ca
index ntr-un tabel de antete de cozi de mesaje. n plus fa de cmpul de permisiuni
generale de comunicare ntre procese, menionat mai sus, structura de date asociat
unei cozi de mesaje conine urmtoarele cmpuri:
Atunci cnd un utilizator invoc apelul sistem msgget pentru a crea un nou descriptor,
nucleul caut n tabela de cozi de mesaje pentru a vedea dac exist vreuna care s
corespund specificaiei dat prin cheie. Dac nu exist nici o intrare care s
corespund cheii, nucleul aloc o nou structur de date de tip coad de mesaje, o
iniializeaz i returneaz utilizatorului un identificator pentru aceast nou structur.
Dac exist deja o astfel de coad de mesaje, atunci nucleul verific drepturile de
acces i revine din apelul sistem.
Procesele folosesc apelul sistem msgsnd pentru a trimite un mesaj, apelul avnd
urmtoarea sintax:
-unde msgqid este descriptorul cozii de mesaje, returnat n mod obinuit de apelul
sistem msgget, msg este un pointer ctre o structur de date -controlat de ctre
utilizator- compus din tipul mesajului (care poate lua valori ntregi) i un ir de
caractere, count specific dimensiunea n octei a irului de caractere msg, iar flag
precizeaz aciunea pe care urmeaz s o ntreprind nucleul, n situaia n care nu
mai are la dispoziie suficient spaiu n buffer-ele de memorie.
254
algoritmul msgsnd
/* trimiterea unui mesaj */
intrri: (1)descriptorul cozii de mesaje
(2)adresa structurii de date pentru mesaje
(3)lungimea mesajului
(4)indicatori /* flags */
ieiri: numrul de octeti efectiv trimii
{
verifica valabilitatea descriptorului i a drepturilor de acces;
while(nu exist spaiu de memorie suficient pt. stocarea mesajului)
{
if(flag-ul specific faptul c procesul nu ateapt)
return;
sleep(eveniment: exist spaiu suficient pt. stocarea mesajului)
}
aloca antet de mesaj;
copiaz mesajul propriu-zis din spaiul user in spaiul nucleu;
actualizeaz structura de date:
-insereaz n list noul antet de mesaj;
-iniializeaz pointerul din antetul de mesaj ctre zona de date;
-nscrie valoarea:-contorului de octei;
-momentelor de timp;
-identificatorului procesului transmitor;
trezete toate procesele care ateapt s citeasc mesaje din coad;
}
Figura 10.4. Algoritmul pentru apelul sistem Msgsnd
n Figura 10.4. nucleul verific dac procesul care trimite un mesaj are drept de
scriere pentru descriptorul respectiv, dac lungimea mesajului nu depete limitele
sistemului, dac lista de mesaje nu conine prea muli octei i dac tipul mesajului are
o valoare ntreag i pozitiv. Dac toate condiiile sunt ndeplinite, nucleul aloc
spaiu pentru mesaj din spaiul liber pentru mesaje, gestionat de ctre o tabel (map)
similar celei care gestioneaz spaiul liber de pe dispozitivul de swap (revedei
seciunea ... .1) i copiaz acolo datele din spaiul utilizatorului. Nucleul aloc un antet
de mesaj pe care-l plaseaz la sfritul listei nlnuite de mesaje, corespunztoare
cozii respective. n antet se nscriu tipul i dimensiunea mesajului, se iniializeaz
antetul pentru a referi irul de caractere ce constituie mesajul propriu-zis, iar n
antetul cozii de mesaje se actualizeaz cmpurile ce conin informaii de ordin statistic
(numrul de mesaje i de octei de date din coada de mesaje, momentele de timp i
identificatorul procesului care a trimis mesajul). Apoi, nucleul trezete procesele care
ateptau sosirea unui mesaj n coada de mesaje. Dac numrul de octei depete
limita cozii de mesaje, procesul care trimite mesajul este trecut n starea sleep, pn la
eliberarea spaiului din coada de mesaje, prin trimiterea altor mesaje deja existente
n coad. Dac procesul a semnalizat nucleului s nu-l treac n ateptare (cu ajutorul
flag-ului IPC_NOWAIT), atunci el revine imediat din apelul sistem, cu eroare. Figura
10.5 prezint mesajele dintr-o coad, evideniind antetele de mesaje, listele nlnuite
de antete de mesaje i pointerii din antetele de mesaje ctre zona de date.
255
unde id este descriptorul de mesaj, msg este adresa unei structuri de date a
utilizatorului n care se va scrie mesajul primit, maxcount este dimensiunea irului de
caractere din structura de date msg, type specific tipul de mesaj pe care utilizatorul
dorete s-l citeasc, iar flag precizeaz ce trebuie s fac nucleul dac nu exist
mesaje n coada de mesaje. Valoarea ntoars de apel, count, reprezint numrul de
octei de date efectiv primii de ctre utilizator.
n Figura 10.7. nucleul verific dac utilizatorul are drepturile necesare de acces la
coada de mesaje. Dac mesajul cerut de utilizator are valoarea din cmpul type egal
cu 0, nucleul va localiza primul mesaj din lista nlnuit. Dac lungimea mesajului
este mai mic sau egal cu dimensiunea cerut de utilizator, atunci nucleul copiaz
mesajul propriu-zis n structura de date a utilizatorului i actualizeaz n mod
corespunztor structurile de date ale cozii de mesaje: -scade valoarea contorului de
mesaje aflate n list i numrul de octei de date din coada de mesaje, nscrie
momentul recepionrii mesajului i identificatorul procesului care a recepionat
mesajul, reface lista nlnuit ca urmare a eliminrii mesajului i elibereaz spaiul n
care a fost memorat mesajul. Dac exist procese care doresc s trimit mesaje i
sunt n ateptare ca urmare a faptului c nu a existat spaiu suficient n lista de
mesaje, atunci nucleul le trezete. Dac lungimea mesajului este mai mare dect
256
struct msgform
/* descrierea formei mesajului: */
{ long mtype;
/* -tipul mesajului; */
char mtext[256]; /* -coninutul mesajului; */
};
main()
{
struct msgform msg;
int msgid, pid, *pint;
msgid=msgget(MSGKEY, 0777);/* obinerea identificatorului asociat */
/* mesajului cu cheia MSGKEY
*/
pid=getpid();
pint=(int *) msg.text; /* se copiaz pid-ul ca text al mesajului */
msg.type=1;
msgsnd(msgid, &msg, sizeof(int), 0);
msgrcv(msgid, &msg, 256, pid, 0); /* pid-ul este folosit drept */
/* tip al mesajului
*/
printf(client: recepioneaz de la pid %d\n, *pint);
}
Figura 10.6. Un proces client
Prin stabilirea corespunztoare a valorii parametrului type, un proces poate recepiona
mesaje de un anumit tip. Dac valoarea este un ntreg pozitiv, atunci nucleul ntoarce
primul mesaj de tipul respectiv. Dac valoarea este un ntreg negativ, atunci nucleul
caut tipul cel mai mic ca valoare dintre toate mesajele din coada de mesaje,
presupus a fi mai mic sau egal n valoare absolut dect valoarea type, i ntoarce
primul mesaj de acest tip. De exemplu, dac o coad conine trei mesaje, ale cror
tipuri sunt 3, 2 i respectiv 1, i dac un utilizator cere un mesaj cu valoarea pentru
tip -2, atunci nucleul ntoarce mesajul care are tipul 1, din cadrul cozii de mesaje. n
toate cazurile, dac nici un mesaj din coada de mesaje nu satisface condiia de tip din
cererea de recepionare, nucleul trece procesul n starea de sleep, dac acesta nu a
specificat revenirea imediat din contextul nucleu prin poziionarea bitului
IPC_NOWAIT din cadrul flag-ului.
257
258
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#define MSGKEY 75 /*cheia mesajului=index n tabela de mesaje */
struct msgform
/* descrierea formei mesajului: */
{ long mtype;
/* -tipul mesajului; */
char mtext[256]; /* -coninutul mesajului; */
} msg;
int msgid;
main()
{
int i, pid, *pint;
extern cleanup();
for(i=0; i<20; i++)
signal(i, cleanup());
msgid=msgget(MSGKEY, 0777|IPC_CREAT);
for(;;)
{
msgrcv(msgid, &msg, 256, 1, 0);
pint=(int *) msg.mtext;
pid= *pint;
printf(server: recepioneaz de la pid %d\n, pid);
msg.mtype=pid;
*pint=getpid();
msgsnd(msgid, &msg, sizeof(int), 0);
}
}
cleanup()
{
msgctl(msgid, IPC_RMID, 0);
exit();
}
Figura 10.8. Un proces server
Mesajele sunt formate din perechi tip-date, unde datele din fiier formeaz un ir de
octei. Prefixul type permite proceselor s selecteze, dac se dorete, mesaje de un
anumit tip, facilitate decare nu se putea beneficia cu uurin n cadrul sistemului de
fiiere. Astfel, procesele pot extrage mesaje de un anumit tip din coada de mesaje, n
ordinea n care acestea sosesc, iar nucleul pstreaz ordinea corect. Dei este
posibil implementarea, la nivel utilizator, a unei scheme de comunicare prin fiiere,
comunicarea prin mesaje ofer aplicaiilor o modalitate mai eficient de transfer al
datelor ntre procese.
Un proces poate inspecta starea unui descriptor de mesaj, i poate stabili valoarea i
poate terge un descriptor de mesaj cu ajutorul apelului sistem msgctl. Sintaxa
apelului este
unde id identific descriptorul de mesaj, cmd precizeaz tipul comenzii, iar mstatbuf
reprezint adresa structurii de date utilizator care va conine parametrii de control sau
rezultatele unei interogri. Implementarea apelului sistem este simpl, n anex
precizndu-se n detaliu parametrii.
ntorcndu-ne la exemplul din figura 10.8 cu procesul server, acesta recepioneaz
semnalele i invoc funcia cleanup pentru a terge coada de mesaje din memoria
sistemului. Dac procesul server nu a recepionat semnalele, sau dac primete un
semnal SIGKILL (care nu poate fi tratat), atunci coada de mesaje va rmne n sistem,
chiar dac nici un proces nu o mai refer. ncercrile ulterioare de a crea (n
exclusivitate) o nou coad de mesaje pe baza cheii date, vor eua pn n momentul
n care vechea coad va fi tears.
Procesele pot comunica direct unele cu celelalte prin folosirea n comun a unor pri
din spaiul lor virtual de memorie i prin scrierea i citirea datelor memorate n
memoria comun. Apelurile sistem pentru manipularea zonelor de memorie comun
sunt similare apelurilor sistem dedicate comunicaiei prin mesaje. Apelul sistem
shmget creaz o nou zon (regiune) comun de memorie sau ntoarce una existent,
apelul sistem shmat ataeaz la nivel logic o regiune de memorie la spaiul virtual de
adrese al unui proces, apelul sistem shmdt detaeaz o regiune de spaiul virtual de
adrese al unui proces, iar apelul sistem shmctl manipuleaz diveri parametri asociai
zonelor comune de memorie. Procesele scriu n -i citesc date din- memoria comun
utiliznd aceleai instruciuni main pe care le utilizeaz i la scrierea ori citirea din
memoria obinuit. Dup ataarea unei zone de memorie comun, aceasta devine
parte a spaiului virtual de adrese al procesului, accesibil n acelai mod n care sunt
accesibile i celelalte adrese virtuale; nu sunt necesare apeluri sistem pentru scrierea
sau citirea datelor din zona de memorie comun.
Sintaxa apelului sistem shmget este urmtoarea
unde size reprezint numrul de octei din regiunea de memorie. Nucleul caut cheia
key n tabela cu zonele comune de memorie: dac gsete n aceast tabel o intrare
care s corespund cheii i dac drepturile de acces sunt validate, atunci ntoarce
descriptorul acelei intrri din tabel. Dac nu gsete o intrare creia s-i corespund
cheia key, i dac utilizatorul a dat indicatorului flag valoarea IPC_CREAT, n scopul
crerii unei noi regiuni comune de memorie, atunci nucleul verific dac valoarea
parametrului size se situeaz ntre valorile limit minim i maxim de memorie ale
sistemului i apoi aloc o structur de date pentru o regiune de memorie, utiliznd
algoritmul allocreg. Nucleul memoreaz n tabela cu zonele comune de memorie
(Shared Memory Table) drepturile drepturile de acces, dimensiunea i un pointer ctre
intrarea din tabela cu regiunile de memorie (Region Table) (vezi figura 10.19.) i
stabilete valoarea unui indicator pentru a arta c regiunii nu i este asociat nici o
cantitate (pagin) de memorie. Nucleul aloc regiunii memorie (tabele de pagini
260
unde id, returnat de apelul sistem anterior (shmget), identific regiunea de memorie
comun, addr reprezint adresa virtual unde utilizatorul dorete s ataeze zona
comun de memorie, iar flags specific dac regiunea este accesibil numai pentru
citire (read-only) i dac nucleul s trunchieze adresa specificat de utilizator.
Valoarea ntoars, virtaddr, reprezint adresa virtual la care nucleul a ataat
regiunea, care nu trebuie s fie neaprat egal cu valoarea cerut de ctre proces.
La execuia apelului sistem shmat nucleul verific dac procesul are drepturile
necesare de acces la regiunea de memorie (figura 10.10.). Acesta examineaz adresa
specificat de ctre utilizator: dac este zero, atunci nucleul alege o adres virtual
convenabil.
261
unde addr reprezint adresa virtual ntoars de un apel shmat anterior. Dei ar prea
mai logic ca apelul shmdt s primeasc drept parametru un identificator, se
ntrebuineaz totui adresa virtual a regiunii de memorie comun pentru ca procesul
s poat face distincie ntre mai multe instane ale unei regiuni de memorie comun,
care sunt ataate la spaiul virtual de adrese al procesului, i pentru c identificatorul
ar putea s fi fost ters. Nucleul caut regiunea procesului ataat la adresa virtual
262
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define SHMKEY 75
#define K 1024
int shmid;
main()
{
int i,*pint;
char *addr1,*addr2;
extern char *shmat();
extern cleanup();
for(i=0; i<20; i++)
signal(i,cleanup);
shmid=shmget(SHMKEY, 128*K, 0777|IPC_CREAT);
addr1=shmat(shmid, 0, 0);
addr2=shmat(shmid, 0, 0);
printf(addr1 0x%x addr2 0x%x\n, addr1, addr2);
pint=(int *) addr1;
for(i=0; i<256; i++)
*pint++=i;
pint=(int *) addr1;
*pint=256;
pint=(int *) addr2;
for(i=0; i<256; i++)
printf(index %d\tvalue %d\n, i, *pint++);
pause();
cleanup()
{
shmctl(shmid, IPC_RMID, 0);
exit();
}
263
Figura 10.12. arat un alt proces care ataeaz aceeai regiune (acesta preia numai
64 KO, pentru a ilustra faptul c fiecare proces poate ataa o cantitate diferit de
memorie dintr-o regiune de memorie comun;) procesul respectiv ateapt pn cnd
primul proces scrie o valoare nenul n primul cuvnt al regiunii de memorie comun i
apoi citete coninutul regiunii de memorie comun. Primul proces execut un apel
pause pentru a permite execuia celui de al doilea; cnd primul proces primete un
semnal, atunci el detaeaz regiunea de memorie comun.
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#define SHMKEY 75
#define K 1024
int shmid;
main()
{
int i,*pint;
char *addr;
extern char *shmat();
shmid=shmget(SHMKEY, 64*K, 0777);
addr=shmat(shmid, 0, 0);
pint=(int *) addr;
while(*pint==0)
;
for(i=0; i<256; i++)
printf(%d\n,*pint++);
}
Figura 10.12. Folosirea n comun a memoriei de ctre procese
Pentru examinarea strii i stabilirea valorilor parametrilor unei regiuni de memorie
comun, un proces utilizeaz apelul sistem shmctl, care are urmtoarea sintax:
procedura P(s);
{
e(s)=e(s)-1; /* se micoreaz contorul de resurse disponibile; */
if(e(s)<0) /* nu sunt resurse la dispoziie, atunci *
stare(r)=blocat; /* pune procesul r n firul de ateptare ; */
}
265
procedura V(s);
{
e(s)=e(s)+1; /* se mrete contorul de resurse disponibile; */
if(e(s)<0) /* mai snt cereri de resurse nesatisfcute */
stare(q)=activ; /* scoate procesul q din firul de ateptare ; */
}
nP(s) := nP(s) + 1;
dac nP(s) eo(s) + nV(s)
atunci nf(s) = nf(s) - 1;
266
procedura PRODUCTOR();
{
while(TRUE) /* ciclu infinit; */
{
PRODUCE_BUFFER(buf);/*genereaz informaii pt. a fi scrise n buffer;*/
P(gol); /* cere acces n setul de buffere;*/
P(mutex); /* intrare n regiunea critic; */
SCRIE_BUFFER(buf);/* scrie informaia generat n bufferul pus la */
/* dispoziie; */
V(mutex); /* prsirea regiunii critice; */
V(plin); /* activarea unui proces aflat n ateptare; */
}
}
procedura CONSUMATOR();
{
while(TRUE) /* ciclu infinit; */
{
267
Pe lng aspectele pozitive ale soluiei se pot semnala i unele limite ale metodei:
-n sistemele mari este dificil folosirea semafoarelor;
-exist posibilitatea ca, din cauza unor erori de programare, s se sar n mod
accidental peste executarea lui P, ceea ce duce la accesul neprotejat la regiunile
critice;
-n mod analog, dac se sare peste execuia lui V, se poate ajunge la fenomenul de
blocare;
-n procesul de compilare nu se poate verifica utilizarea corect a semafoarelor;
268
Apelurile sistem pentru lucrul cu semafoare sunt, semget pentru a crea i pentru a
obine accesul la un set de semafoare, semctl pentru executarea unor diverse
operaiuni de control asupra setului de semafoare i semop pentru a modifica valorile
semafoarelor.
269
unde id este descriptorul ntors de apelul semget, oplist este un pointer ctre un
vector de operaii asupra semaforului, iar count este dimensiunea vectorului. Valoarea
ntoars, oldval, reprezint valoarea ultimului semafor din set asupra cruia s-au fcut
operaii, nainte de operaia respectiv. Formatul fiecrui element din oplist este
urmtorul:
-numrul semaforului, care identific
semafoare pe care se opereaz;
intrarea
-operaia propriu-zis;
-valoarea indicatorilor (flags)
270
corespunztoare
vectorului
de
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#define SEMKEY 75
int semid;
unsigned int count;
/* definiia structurii de date sembuf din fiierul sys/sem.h> */
/* struct sembuf
*/
/* {
*/
/*
unsigned short sem_num;
*/
/*
short sem_op;
*/
/*
short sem_flg;
*/
/* };
*/
struct sembuf psembuf,vsembuf; /* operaii corespunztoare lui P si V */
main(argc, argv)
int argc;
char *argv[];
{
int i, first, second;
short initarray[2], outarray[2];
extern cleanup();
if(argc==1)
{
for(i=0;i<20;i++)
signal(i, cleanup());
semid=semget(SEMKEY, 2, 0777|IPC_CREAT);
initarray[0]=initarray[1]=1;
semctl(semid, 2, SETALL, initarray);
semctl(semid, 2, GETALL, outarray);
printf(valori initiale semafor %d %d\n, outarray[0],outarray[1]);
pause(); /* trece n sleep pn la trezirea de ctre un semnal */
}
else if(argv[1][0]==a)
{
first=0;
second=1;
}
else
{
first=1;
second=0;
}
semid=semget(SEMKEY, 2, 0777);
psembuf.sem_op=-1;
psembuf.sem_flg=SEM_UNDO;
vsembuf.sem_op=1;
vsembuf.sem_flg=SEM_UNDO;
for(count=0; ;count++)
{
psembuf.sem_num=first;
semop(semid, &psembuf, 1);
psembuf.sem_num=second;
semop(semid, &psembuf, 1);
printf(procesul %d nr. %D\n, getpid(), count);
vsembuf.sem_num=second;
271
cleanup()
{
semctl(semid, 2, IPC_RMID, 0);
exit();
}
}
/* toate operaiile cu semafoare au reut */
actualizeazinregistrrile de timp, identificatorii proceselor;
return(valoarea iniial a ultimului semafor modificat);
}
Figura 10.15. Algoritmul pentru operarea asupra semafoarelor
a.out &
a.out a &
a.out b &
Atunci cnd programul este rulat fr parametri, procesul creaz un set de semafoare
cu dou elemente, ale cror valori sunt iniializate cu 1. Apoi, procesul execut apelul
pause( ) i trece n starea sleep pn cnd este trezit de un semnal, la tergerea unui
semafor n cadrul funciei cleanup( ). Atunci cnd programul se execut cu parametrul
a, procesul (A) face n cadrul ciclului patru operaii distincte cu semafoarele:
decrementeaz valoarea semaforului 0, decrementeaz valoarea semaforului 1,
execut instruciunea printf i apoi incrementeaz valoarea semaforului 1 i a
semaforului 0. Dac un proces ncearc decrementarea valorii unui semafor care are
deja valoarea 0, atunci este trecut n starea sleep i n consecin semaforul se
consider blocat (locked). Deoarece semafoarele au fost iniializate cu valoarea 1 i
nici un alt proces nu le mai folosete, procesul A nu va trece niciodat n starea sleep,
iar valorile semafoarelor vor bascula ntre valorile 0 i 1. Atunci cnd programul se
execut cu parametrul b, procesul (B) decrementeaz semafoarele 0 i 1 n ordinea
invers celei n care a fcut-o procesul A. Atunci cnd procesele A i B se execut
simultan, poate aprea situaia n care procesul A a blocat semaforul 0 i dorete s
blocheze semaforul 1, dar procesul B a blocat semaforul 1 i dorete s blocheze
semaforul 0. n acest caz, ambele procese trec n starea sleep, fiind n imposibilitatea
de a-i continua execuia. Ele sunt deblocate i i ncheie execuia numai la primirea
unui semnal.
Pentru a evita astfel de probleme, procesele pot executa simultan mai multe
operaiuni asupra semafoarelor. Acest rezultat se poate obine folosind urmtoarele
date i instruciuni:
273
psembuf[0].sem_num=0;
psembuf[1].sem_num=1;
psembuf[0].sem_op=-1;
psembuf[1].sem_op=-1;
semop(semid, psembuf, 2);
274
Semid
Identificator
semafor
de
---------------------------------Numr
de
semafor
---------------------------------
Numr
semafor
de
semafor
-----------------------------------Corecie
Semid
---------------------------------
Corecie
-------------------------------------
--------------------------------
275
Identificator
de
Semid
semafor
-------------------------------------------------------------------------------------Numr
de
Empty
semafor
-------------------------------------------------------------------------------------Corecie
Revenind la figura 10.14., nucleul creaz o structur undo ori de cte ori un proces
decrementeaz valoarea unui semafor i elimin o structur de tip undo ori de cte ori
procesul incrementeaz valoarea unui semafor, deoarece valoarea de corecie din
structura undo devine zero. Figura 10.17. prezint succesiunea evoluiei structurilor de
tip undo n cazul execuiei programului cu parametrul a. Dup prima operaie,
procesul are un singur triplet (o singur structur de tip undo) corespunztoare
numrului de semafor 0 i valorii de corecie 1, iar dup cea de-a doua operaie
procesul dispune i de al doilea triplet, corespunztor numrului de semafor 1 i valorii
de corecie 1. Dac procesul i-ar ncheia execuia n acest moment, atunci nucleul va
parcurge fiecare triplet, adugnd valoarea 1 la fiecare semafor, readucndu-le
valoarea la zero. n mod obinuit, nucleul decrementeaz valoarea de corecie a
semaforului 1 pe timpul celei de a treia operaii, corespunztor creterii valorii
semaforului, i elimin tripletul, deoarece valoarea sa de corecie a devenit zero. Dup
cea de-a patra operaie, procesul nu mai dispune de triplei, deoarecetoate valorile de
corecie vor fi zero.
Operaiile din vectorul de operaii asupra semafoarelor permit proceselor s evite
blocrile, dup cum a fost exemplificat mai sus, dar sunt complicate i majoritatea
aplicaiilor nu are nevoie de ntreaga lor capacitate. Aplicaiile care necesit utilizarea
mai multor semafoare vor trebui s rezolve problema condiiilor de blocare, la nivel
utilizator, pentru ca nucleul s nu conin astfel de apeluri sistem complicate.
Apelul sistem semctl conine o mulime de operaii de control relative la semafoare,
avnd urmtoarea sintax:
semctl(id, number, cmd, arg);
276
union semunion
{
int val;
struct semid_ds *semstat;
unsigned short *array;
} arg;
10.3.
aceast main creaz procese getty (adic procesele server) pentru supravegherea
liniilor i pentru notificarea stabilirii legturii. Dup realizarea fizic a legturii,
procesul client deschide sesiunea, urmnd n acest sens protocolul obinuit: procesul
getty face un apel exec pentru a lansa un proces care execut codul unui interpretor
special de comenzi, uucico, precizat n fiierul /etc/passwd, iar procesul client face un
apel write pentru a scrie secvena de comenzi pe maina de la distan, determinnd
executarea proceselor de pe aceasta n folosul mainii locale.
Comunicaiile prin reea au ridicat o problem sistemelor UNIX, concretizat n faptul
c mesajele trebuie, n mod frecvent, s conin poriuni de date i de informaii de
control. Segmentul de control poate conine informaii de adresare, pentru specificarea
destinaiei unui mesaj. Informaia de adresare este structurat n funcie de tipul de
reea i de protocol utilizate. Prin urmare, procesele trebuie s cunoasc tipul reelei,
n ideea c utilizatorilor trebuie s le fie transparent tipul unui anume fiier, deoarece
toate dispozitivele periferice sunt tratate ca fiiere. Metodele tradiionale de
implementare a comunicrii prin reea se bazeaz n mod consecvent i n mare
msur pe apelul sistem ioctl pentru a preciza informaia de control, dar aceast
abordare nu este generalizat la toate tipurile de reele. O consecin nedorit a
acestui aspect o constituie faptul c este posibil ca programele proiectate pentru o
reea s nu funcioneze pe alte reele.
mbuntirea interfeelor de reea pentru sistemele UNIX a necesitat un efort
semnificativ. Implementarea sub form de fluxuri (streams) specific ultimelor
variante ale System V furnizeaz un mecanism elegant de asigurare a lucrului n reea,
deoarece modulele de implementare a protocoalelor pot fi combinate n mod flexibil
prin includerea lor n stream-uri i deoarece utilizarea lor este uniform la nivel
utilizator. Urmtorul subcapitol descrie socket-urile, care reprezint soluia problemei,
adoptat n cadrul variantei BSD.
Subcapitolul anterior a artat modul n care pot comunica procesele care se execut
pe maini diferite, subliniind faptul c este foarte probabil ca metodele prin care aceste
procese stabilesc legturile, s difere n funcie de protocol i de mediul de transmisie.
Mai mult, aceste metode pot s nu permit comunicarea ntre procesele chiar de pe
aceeai main, deoarece ele presupun existena unui proces server care se afl n
ateptare n cadrul unui apel sistem open sau read, relativ la un dispozitiv. Pentru a
furniza metode generale de comunicare ntre procese i pentru a permite utilizarea
protocoalelor de reea sofisticate, sistemul BSD pune la dispoziie un mecanism
cunoscut sub numele de socket-uri. n acest subcapitol sunt descrise unele aspecte, la
nivel utilizator, ale socket-urilor.
279
280
unde sd este descriptorul de socket, iar address este adresa unei structuri care
precizeaz un indicator al domeniului i protocolului de comunicaie, precizate n cadrul
apelului sistem socket. Parametrul length reprezint lungimea structurii de date
address; fr acest parametru nucleul nu ar ti ct de lung este adresa, deoarece
lungimea acesteia poate diferi de la un domeniu (sau protocol) la altul. De exemplu, n
cadrul domeniului UNIX, o adres este un nume de fiier. Procesul server transform
adresele din apelul bind n socket-uri i face publice numele lor pentru a fi
identificate de ctre procesele client.
Apelul sistem connect cere nucleului s fac o conexiune cu un socket existent:
listen(sd, qlength);
281
unde sd este descriptorul de socket, address indic un vector de date utilizator pe care
nucleul l completeaz cu adresa de retur a procesului client care se conecteaz, iar
addrlen precizeaz dimensiunea acestui vector. La revenirea din apelul accept, nucleul
scrie n addrlen un numr care semnific dimensiunea spaiului ocupat de adres.
Apelul accept ntoarce un nou descriptor de socket, nsd, diferit de descriptorul sd. Un
proces server poate continua s asculte la socket-ul anunat, n timp ce comunic cu
un proces client pe un canal separat de comunicaie (figura 10.19).
Apelurile sistem send i recv transmit date printr-un socket conectat:
unde sd este descriptorul de socket, msg este un pointer ctre datele care urmeaz a
fi trimise, length reprezint lungimea datelor de trimis, iar count este numrul de
octei efectiv trimii. Parametrului flags i se poate atribui valoarea SOF_OOB pentru a
realiza o trimitere out-of-band a unor date, nelegnd prin aceasta faptul c datele
trimise nu sunt considerate c fac parte din schimbul obinuit de date ntre procesele
care comunic. De exemplu, un program de deschidere de sesiune la distan
(remote-login program) poate trimite un mesaj out-of-band pentru a simula
apsarea tastei Del de ctre un utilizator, la un terminal. Sintaxa apelului sistem recv
este
unde buf este locul unde se memoreaz datele care sosesc, length este lungimea
teoretic ateptat a datelor, iar count este numrul de octei efectiv copiai n
programul utilizatorului. Parametrul flags poate primi valoarea peek, pentru un
mesaj care sosete, n scopul examinrii coninutului su fr a-l scoate din coada de
ateptare, sau valoarea out-of-band pentru cazul explicat mai sus. Versiunile pentru
datagrame ale acestor apeluri sistem, sendto i recvfrom, au n plus parametri i
282
pentru adrese. Procesele pot utiliza apelurile sistem read i write n contextul streamsocket-urilor, n locul apelurilor send i recv, dup iniializarea legturii. Astfel,
procesele server se pot ngriji de negocierea protocoalelor de reea i de crearea
proceselor care utilizeaz numai apelurile sistem read i write, ca i cnd acestea ar
lucra cu fiiere obinuite.
Apelul sistem shutdown nchide o legtur cu un socket:
shutdown(sd, mode);
unde mode indic dac partea care trimite datele, partea care le recepioneaz, sau
ambele pri ncheie transmisia datelor. Acest apel informeaz protocoalele de nivel
inferior s ncheie comunicaia prin reea, ns cu meninerea intact a descriptorilor
de socket-uri. Apelul sistem close elimin i descriptorul de socket.
Apelul sistem getsockname furnizeaz numele asociat unui socket, printr-un apel bind
anterior:
283
#include <sys/types.h>
#include <sys/socket.h>
main()
{
int sd, ns;
char buf[256];
struct sockaddr sockaddr;
int fromlen;
sd=socket(AF_UNIX, SOCKSTREAM, 0);
/* asocierea unui nume -- nu includei caracterul nul n nume */
bind(sd, sockname, sizeof(sockname)-1);
listen(sd, 1);
for(;;)
{
ns=accept(sd, &sockaddr, &fromlen);
if(fork()==0)
{
/* codul procesului fiu */
close(sd);
read(ns, buf, sizeof(buf));
printf(serverul citete %s\n, buf);
exit();
}
close(ns);
}
}
Figura 10.20. Un proces server din cadrul domeniului UNIX
Figura 10.21 prezint procesul client corespunztor procesului server. Procesul creaz
un un socket n acelai domeniu ca i serverului emite o cerere connect pentru acelai
sockname, asociat de un server unui socket. La ieirea din apelul connect, procesul
client dispune de un circuit virtual ctre un proces server. n acest exemplu, procesul
client scrie (prin apelul write) un singur mesaj i i ncheie execuia (cu exit).
Dac procesul server furnizeaz servicii proceselor dintr-o reea, atunci n cadrul
apelurilor sale sistem se specific faptul c socket-ul aparine domeniului Internet
(Internet domain), prin
i asociaz (prin apelul bind) o adres de reea furnizat de un name server. Sistemul
BSD dispune de apeluri de bibliotec, care fac aceste funcii. Similar, al doilea
parametru al apelului connect fcut de procesul client, ar trebui s conin informaia
de adres necesar identificrii mainii n reea (sau adresa de rutare cu care s se
trimit mesajele la maina de destinaie, prin maini intermediare), precum i
informaii suplimentare de identificare a unui anumit socket de pe maina de
destinaie. Dac procesul server dorete s asculte att n reea, ct i la procesele
284