Sunteți pe pagina 1din 12

Enuntul problemei pentru acest laborator incepe cu: "Se cere un server si unul sau mai multi clienti"

Pentru comunicarea prin pipe sau FIFO se va si se va adapta corespunzator enuntul, considerand: "Se cere un server si un client" Sunt trei motive pentru care facem aceasta simplificare: 1. Un canal pipe si FIFO este potrivit pentru comunicarea intre doua procese, insa este dificil de folosit pentru comunicarea intre mai mult de doua procese. . Oferim studentilor interesati posibilitati de !eneralizare a solutiei pentru doi sau mai multi clienti: " fie prin !estionarea de server a cate unui canal separat pentru cereri de la fiecare client, " fie prin folosirea unui instrument #semafor, blocare de fisier etc.$ de acces e%clusiv al unui client la canal, &. 'ceeasi problema va constitui tema pentru un alt laborator, unde se vor cere efectiv mai multi clienti. (in acest motiv, rezolvarea problemei trebuie abordata modular. 'stfel, partile de comunicare din cod sa fie #pe cat posibil$ separate de partile specifice din businessul problemei. 'stfel, parti din solutie pot fi folosite la solutionarea problemei prin alte tipuri de canale de comunicare. In cele ce urmeaza este prezentata o problema, rezolvata folosind comunicarea prin pipe, prin FIFO si prin popen. Solutia este implementata in limba)ul *. +a sfarsitul prezentarii sunt date si sursele P,t-on ec-ivalente. E%emplu: lista limitata de fisiere cu nume de anumita forma. """""""""""""""""""""""""""""""""""""""""""""""""""""""""""" Enuntul problemei este: Se cere un server si un client. *lientul trimite serverului un intre! l si un strin! s. Serverul ii intoarce clientului lista a ma%imum l fisiere din directorul lui curent, ale caror nume se termina cu strin!ul s. .om descrie implementarea separat pe functionalitati. Pentru fiecare functionalitate am intocmit o sursa separata. /ai intai vom construi doua functii cu acelasi rol, acela de a furniza lista numelor de fisiere: /esa) 0dir#int l, c-ar 0s$ """ /esa) 0dirPopen#int l, c-ar 0s$ """""""" .om descrie mai intai tipul de date /esa). El va diferi de

la un tip de canal la altul, insa pentru functiile de mai sus aceasta diferenta nu le va influenta raspunsurile. Structura /esa) este: 1""P+US""2 1""""""""""""" /'3S """"""""""""""2 4lun!4 4s 4 4""""4""""""""""4%%%%%%%%%%%%%%%%%%%%%%%%%%%%4""""""4 4 4 2 """""""""""""" lun! """"""""""""""""1 lun! este un intre! ce contine lun!imea efectiva a continutului mesa)ului. 5ona de P+US octeti contine cativa intre!i, depinde de tipul canalului pe care se comunica. s este un tablou de ma%imum /'3S caractere, aflat in partea finala a mesalului. Evident, in functie de natura problemei utilizatorul poate sa isi defineasca suprapuneri convenabile #union$ in /esa). Sursa dir.c contine functiile dir si dirPopen. 'ceste functii """"" """ """""""" sunt independente de tipul canalului de comunicatie: /esa) 0dir#int l, c-ar 0s$ 6 static /esa) resp7 (I8 0dirp7 struct dirent 0d7 c-ar 0p, 09, 0n7 int i7 p : resp.s7 resp.lun! : ;7 dirp : opendir #"."$7 for #i:;7 i<l7 $ 6 d : readdir #dirp$7 if #d :: =U++$ brea>7 n : d"?d@name7 if #strlen#n$ < strlen#s$$ continue7 if #strcmp#nAstrlen#n$"strlen#s$, s$ B: ;$ continue7 if #resp.lun!Astrlen#n$A1 ? /'3S$ brea>7 iAA7 strcp,#p, n$7 resp.lun! A: strlen#n$A17 p A: strlen#n$A17 C closedir #dirp$7 resp.lun! A: P+US7 return Dresp7 C /esa) 0dirPopen#int l, c-ar 0s$ 6 static /esa) resp7 FI+E 0fin7 c-ar nE/'3+F, 0p, 09, comandaE/'3+F7 int i7 strcp,#comanda, "ls "1 0"$7 strcat#comanda, s$7

fin : popen#comanda, "r"$7 p : resp.s7 resp.lun! : ;7 for #i:;7 i<l7 $ 6 9 : f!ets#n, /'3+, fin$7 if #9 :: =U++$ brea>7 nEstrlen#n$"1F : G2;G7 if #resp.lun!Astrlen#n$A1 ? /'3S$ brea>7 iAA7 strcp,#p, n$7 resp.lun! A: strlen#n$A17 p A: strlen#n$A17 C pclose #fin$7 resp.lun! A: P+US7 return Dresp7 C 'mbele functii primesc intre!ul l si strin!ul s precizati in enuntul problemei "lista a ma%imum l nume de fisiere din directorul curent al caror nume se termina cu s". 'mbele functi intorc un pointer la un /esa) care contine lista numelor. /esa)ul contine in s succesiunea de strin!uri #conventie *$ cu numele fisierelor raspuns, iar lun! suma lun!imilor acestor strin!uri #plus zerourile terminale$, plus P+US. Functia dir obtine raspunsul folosind apelurile sistem opendir, readdir, closedir si structurile (I80, struct dirent. Functia dirPopen obtine raspunsul folosind apelul sistem popen. *u acesta se apeleaza popen#"ls "1 0.c"$, daca strin!ul s este .c. Functia dirPopen capteaza iesirea standard a acestui apel popen, de unde e%tra!e primele l linii. #(in e%ecutii se poate observa ca cele doua nu intorc neaparat numele acelorasi fisiereB$. Pentru comunicarea prin pipe si prin FIFO structura mesa)ului este descrisa in sursa mesa).-: """"""" Hdefine /'3S 1;;;; Hdefine /'3+ 1;;; t,pedef struct 6 int lun!7 int i7 c-ar sE/'3SF7 C /esa)7 Hdefine P+US #sizeof#int$$ *itirea 1 scrierea unui /esa) la comunicarea prin pipe sau FIFO se face in doua etape: 1. Se scrie 1 citeste lun!. . Se fac scrieri 1 citiri repetate, pana cand sunt sc-imbati toti octetii continutului mesa)ului.

(e ce a fost necesara o astfel de abordareI (in cauza functionarii apelurilor sistem read si Jrite. 'ceste apeluri sunt atomice, insa nu asi!ura sc-imbul numarului total de octeti solicitati #al treilea ar!ument al apelurilor read si Jrite$. 'ceste apeluri intorc, la sfarsit, numarul de octeti efectiv sc-imbati. (in aceasta cauza este dificila comunicarea prin pipe sau FIFO intre mai mult de doua procese: procesele care citesc nu stiu de la ce procese cititoare isi preia octetiiB Pentru implementarea sc-imbului de mesa)e sunt folosite functiile 8ead, Krite, 8ead/es, Krite/es. """" """"" """"""" """""""" Primele doua aplica repetat apeluri read, Jrite pana la sc-imbarea a e%act n octeti, n parametru de intrare. 8ead/es si Krite/es sc-imba mai intai lun!imea continutului, dupa care cere sc-imbul complet al acestuia. *ele patru functii sunt prezentate in sursa 8eadKrite.c """"""""""" void 8ead#int f, c-ar 0t, int n$ 6 c-ar 0p7 int i, c7 for #p:t, c:n7 7 $ 6 i : read#f, p, c$7 if #i :: c$ return7 c ": i7 p A: i7 C C void Krite#int f, c-ar 0t, int n$ 6 c-ar 0p7 int i, c7 for #p:t, c:n7 c7 $ 6 i : Jrite#f, p, c$7 if #i :: c$ return7 c ": i7 p A: i7 C C /esa) 08ead/es#int canal$ 6 static /esa) mesa)7 read#canal, #c-ar0$Dmesa).lun!, sizeof#int$$7 8ead#canal, #c-ar0$Dmesa)Asizeof#int$, mesa).lun!$7 return Dmesa)7 C void Krite/es#int canal, /esa) 0pm$ 6 Jrite#canal, #c-ar0$pm, sizeof#int$$7 Krite#canal, #c-ar0$pmAsizeof#int$, pm"?lun!$7 C 'ctiunea principala a serverului este diri)ata de functia void parinte#int in, in out$

""""""" Parametrii sunt -andle ale canalelor prin care citeste mesa)e de la clienti, respectiv scrie raspunsurile spre clienti. (upa caz, aceste -andle pot fi descriptori pipe, descriptori FIFO, sau, cum vom vedea in laboratoarele viitoare, descriptori de memorie parta)ata sau de cozi de mesa)e. 'ctiunea acestei functii este simpla: citeste in mod repetat cate un mesa) de la un client, apeleaza dir #sau dirPopen$, dupa care scrie in mesa) raspunsul pentru client. Sursa parinte.c este: """"""""" void parinte#int in, int out$ 6 /esa) 0pm7 for # 7 7 $ 6 pm : 8ead/es#in$7 11pm : dirPopen#pm"?i, pm"?s$7 pm : dir#pm"?i, pm"?s$7 Krite/es#out, pm$7 C C 'ctiunea principala a clientului este diri)ata de functia void fiu#int in, in out$ """ +a fel ca la server, parametrii sunt -andle ale canalelor prin care citeste mesa)e de la server, respectiv scrie cereri catre server. (upa caz, aceste -andle pot fi descriptori pipe, descriptori FIFO, sau, cum vom vedea in laboratoarele viitoare, descriptori de memorie parta)ata sau de cozi de mesa)e. *lientul citeste in mod repetat de la intrarea standard cate un numar l si un strin! s. (upa fiecare citire prepara un mesa), pe care il trimite la server. 'poi citeste mesa)ul de raspuns primit de la server si il listeaza pe iesirea standard. Sursa fiu.c descrie actiunea clientului: """"" void fiu#int in, int out$ 6 /esa) 0pm, mesa)7 c-ar 0pc,linieE/'3+F7 int i7 for # 7 7 $ 6 printf#"(ati: numar4sufi%: "$7 pc : #c-ar0$f!ets#linie, /'3+, stdin$7 if #pc :: =U++$ brea>7 linieEstrlen#linie$"1F : G2;G7 pc : strstr#linie, "4"$7 if #pc :: =U++$ continue7 mesa).i : atoi#linie$7 strcp,#mesa).s, pcA1$7

mesa).lun! : P+US A strlen#mesa).s$ A 17 Krite/es#out, Dmesa)$7 pm : 8ead/es#in$7 pc : pm"?s7 printf#"Ld2n",pm"?lun!$7 for #i : P+US7 i < pm"?lun!7 $ 6 printf#"Ld Ls2n", i, pc$7 i A: strlen#pc$ A 17 pc A: strlen#pc$ A 17 C C C In sfarsit, vom prezenta pro!ramele principale. Prima varianta implementeaza comunicarea prin pipe si este descrisa in sursa pipe.c: """"""" Hinclude <dirent.-? Hinclude <strin!.-? Hinclude <stdio.-? Hinclude <stdlib.-? Hinclude "mesa).-" Hinclude "8eadKrite.c" Hinclude "dir.c" Hinclude "parinte.c" Hinclude "fiu.c" main#$ 6 int fpE F, pfE F, pid7 11 (oua pipe, fp: fiu"?parinte, pf: parinte"?fiu if #pipe#fp$ < ; 44 pipe#pf$ < ;$ e%it#1$7 pid : for>#$7 if #pid < ;$ e%it# $7 if #pid ? ;$ 6 11 *odul serverului #parintelui$ fclose#stdin$7 fclose#stdout$7 close#fpE1F$7 close#pfE;F$7 parinte#fpE;F, pfE1F$7 C else 6 11 *odul clientului #fiului$ close#fpE;F$7 close#pfE1F$7 fiu#pfE;F, fpE1F$7 close#pfE;F$7 close#fpE1F$7 C C (e remarcat faptul ca atat la server cat si la client sunt inc-ise toate fisierele care nu sunt necesare. Prin aceasta se reduce consumul !lobal de resurse #fisiere desc-ise$, precum si securizeaza respectarea directiei de transmitere. .arianta a doua implementeaza comunicarea prin FIFO.

/ai intai sunt creeate in directorul curent doua FIFO"uri: M m>fifo fifo1 M m>fifo fifo Inainte de aceasta, daca aceste FIFO"uri de)a e%ista, ele se ster! cu: M rm fifo1 M rm fifo (eoarece si clientul si serverul sunt ai aceluiasi user, am preferat ca cele doua FIFO"uri sa se afle in directorul curent. (aca cele doua procese apartin la useri diferiti, atunci este convenabil ca FIFO"urile sa fie 1tmp1fifo1 si 1tmp1fifo . Sursa serverului este fifos.c: """""""" Hinclude <dirent.-? Hinclude <strin!.-? Hinclude <stdio.-? Hinclude <stdlib.-? Hinclude <fcntl.-? Hinclude "mesa).-" Hinclude "8eadKrite.c" Hinclude "dir.c" Hinclude "parinte.c" main#$ 6 int f1, f 7 fclose#stdin$7 fclose#stdout$7 f1 : open#"fifo1", O@K8O=+N$7 f : open#"fifo ", O@8(O=+N$7 parinte#f , f1$7 C Sursa clientului este fifoc.c: """"""" Hinclude <strin!.-? Hinclude <stdio.-? Hinclude <fcntl.-? Hinclude "mesa).-" Hinclude "8eadKrite.c" Hinclude "fiu.c" main#$ 6 int f1, f 7 f1 : open#"fifo1", O@8(O=+N$7 f : open#"fifo ", O@K8O=+N$7 fiu#f1, f $7 close#f1$7 close#f $7 C Iata cateva e%ecutii cu popen sau fara, cu pipe sau FIFO """""""""""""""

florinOflorin"laptop:P1probleme1UPipe"QM florinOflorin"laptop:P1probleme1UPipe"QM florinOflorin"laptop:P1probleme1UPipe"QM (ati: numar4sufi%: R4.c ST S fiu.c 1; 8eadKrite.c parinte.c & fifos.c S; pipe.c (ati: numar4sufi%: U* florinOflorin"laptop:P1probleme1UPipe"QM florinOflorin"laptop:P1probleme1UPipe"QM florinOflorin"laptop:P1probleme1UPipe"QM (ati: numar4sufi%: R4.c S& S fifoc.c 1 fifos.c ; fiu.c V parinte.c &V pipe.c (ati: numar4sufi%: U* florinOflorin"laptop:P1probleme1UPipe"QM florinOflorin"laptop:P1probleme1UPipe"QM florinOflorin"laptop:P1probleme1UPipe"QM florinOflorin"laptop:P1probleme1UPipe"QM florinOflorin"laptop:P1probleme1UPipe"QM florinOflorin"laptop:P1probleme1UPipe"QM E1F ;VV florinOflorin"laptop:P1probleme1UPipe"QM (ati: numar4sufi%: R4.c S& S fifoc.c 1 fifos.c ; fiu.c V parinte.c &V pipe.c (ati: numar4sufi%: U* florinOflorin"laptop:P1probleme1UPipe"QM florinOflorin"laptop:P1probleme1UPipe"QM florinOflorin"laptop:P1probleme1UPipe"QM E1FA Werminated .1s florinOflorin"laptop:P1probleme1UPipe"QM florinOflorin"laptop:P1probleme1UPipe"QM florinOflorin"laptop:P1probleme1UPipe"QM florinOflorin"laptop:P1probleme1UPipe"QM florinOflorin"laptop:P1probleme1UPipe"QM florinOflorin"laptop:P1probleme1UPipe"QM E1F 1S florinOflorin"laptop:P1probleme1UPipe"QM (ati: numar4sufi%: R4.c ST S fiu.c 1; 8eadKrite.c parinte.c & fifos.c S; pipe.c

Hdir !cc pipe.c .1a.out

HdirPopen !cc pipe.c .1a.out

m>fifo fifo1 m>fifo fifo HdirPopen !cc "o s fifos.c !cc "o c fifoc.c .1sD .1c

Hdir >ill ;VV rm fifo1 rm fifo m>fifo fifo1 m>fifo fifo !cc "o s fifos.c !cc "o c fifoc.c .1sD .1c

(ati: numar4sufi%: Sursele P,t-on ec-ivalente: /esa).p, """""""" class /esa): /'3S : 1;;;; SI5EOFI=W : 1; H privit ca te%t P+US : SI5EOFI=W lun! : ; i : ; s : E""F def @@init@@#self, ser$: if ser :: =one: return self.lun! : int#serE:self.SI5EOFI=WF$ self.i : int#serEself.SI5EOFI=W: 0self.SI5EOFI=WF$ self.s : serE 0self.SI5EOFI=W:self.SI5EOFI=WAself.lun!F.split#"4"$ def @@str@@#self$: ser : "" for l in self.s: ser A: lA"4" ser : serE:"1F ser : self.i s#self.lun!$Aself.i s#self.i$Aser return ser def i s#self, i$: sir : ";;;;;;;;;;;;;;;;;;"AXiX if sir.endsJit-#"+"$: sir : sirE:"1F return sirE"self.SI5EOFI=W:F dir.p, """""" import os import /esa) def dir#l, s$: mesa) : /esa)./esa)#=one$ mesa).s : EF lun! : ; i : 1 for linie in os.listdir#"."$: if i ? l: brea> if lun! A len#linie$ A len#mesa).s$ ? mesa)./'3S: brea> if len#linie$ < len#s$: continue if linieElen#linie$" len#s$:F B: s: continue mesa).s A: ElinieF i A: 1 lun! A: len#linie$ mesa).lun! : mesa).P+US A lun! A len#mesa).s$ " 1 if len#mesa).s$ :: ;: mesa).lun! A: 1 return mesa) def dirPopen#l, s$: mesa) : /esa)./esa)#=one$

mesa).s : EF lun! : ; i : 1 for linie in os.popen#"ls "1", "r"$.readlines#$: linie : linieE:"1F if i ? l: brea> if lun! A len#linie$ A len#mesa).s$ ? mesa)./'3S: brea> if len#linie$ < len#s$: continue if linieElen#linie$" len#s$:F B: s: continue mesa).s A: ElinieF i A: 1 lun! A: len#linie$ mesa).lun! : mesa).P+US A lun! A len#mesa).s$ " 1 if len#mesa).s$ :: ;: mesa).lun! A: 1 return mesa) 8eadKrite.p, """""""""""" import /esa) import os def 8ead#f, n$: c : n sir : "" J-ile c ? ;: s : os.read#f, c$7 sir A: s c ": len#s$ return sir def Krite#f, sir$: c : len#sir$ p : ; J-ile c ? ;: i : os.Jrite#f, sirEp:F$ c ": i p A: i def 8ead/es#canal$: lun! : os.read#canal, /esa)./esa).SI5EOFI=W$ ser : 8ead#canal, int#lun!$$ return /esa)./esa)#lun!Aser$ def Krite/es#canal, mesa)$: lun! : mesa).SI5EOFI=WAmesa).lun! Krite#canal, str#mesa)$E:lun!F$ parinte.p, """""""""" import 8eadKrite import dir def parinte#i=, out$: J-ile Wrue: mesa) : 8eadKrite.8ead/es#i=$ mesa) : dir.dir#mesa).i, mesa).sE;F$ Hmesa) : dir.dirPopen#mesa).i, mesa).sE;F$

8eadKrite.Krite/es#out, mesa)$ fiu.p, """""" import s,s import /esa) import 8eadKrite def fiu#i=, out$: J-ile Wrue: print "(ati: numar4sufi%: ", linie : s,s.stdin.readline#$ if not linie: brea> linie : linieE:"1F pc : linie.find#"4"$ if pc < ;: continue mesa) : /esa)./esa)#=one$ mesa).s : EF mesa).i : int#linieE:pcF$ mesa).s A: ElinieEpcA1:FF mesa).lun! : mesa).P+US A len#mesa).sE;F$ 8eadKrite.Krite/es#out, mesa)$ mesa) : 8eadKrite.8ead/es#i=$ for l in mesa).s: print l pipe.p, """"""" import s,s import os import parinte import fiu def main#$: fp : os.pipe#$ pf : os.pipe#$ pid : os.for>#$ if pid < ;: e%it# $ if pid ? ;: H *odul serverului #parintelui$ s,s.stdin.close#$ s,s.stdout.close#$ os.close#fpE1F$ os.close#pfE;F$ parinte.parinte#fpE;F, pfE1F$ else: H *odul clientului #fiului$ os.close#fpE;F$ os.close#pfE1F$ fiu.fiu#pfE;F, fpE1F$ os.close#pfE;F$ os.close#fpE1F$ main#$ fifos.p,

"""""""" import s,s import os import parinte def main#$: s,s.stdin.close#$ s,s.stdout.close# f1 : os.open#"fifo1", os.O@K8O=+N, ;VVV$ f : os.open#"fifo ", os.O@8(O=+N, ;VVV$ parinte.parinte#f , f1$ main#$ fifoc.p, """""""" import os import fiu def main#$: f1 : os.open#"fifo1", os.O@8(O=+N, ;VVV$ f : os.open#"fifo ", os.O@K8O=+N, ;VVV$ fiu.fiu#f1, f $ os.close#f1$ os.close#f $ main#$

S-ar putea să vă placă și