460 likes | 771 Views
2 paskaita. 200 6 m. Komunikacija tarp procesų (IPC). Operacinė sistema vienu metu gali vykdyti eilę tarpusavyje konkuruojančių taikomųjų programų.
E N D
2 paskaita 2006 m. Nijolė Sarafinienė
Komunikacija tarp procesų (IPC) • Operacinė sistema vienu metu gali vykdyti eilę tarpusavyje konkuruojančių taikomųjų programų. • Taikomosios programos gali aptarnauti daug vartotojų užklausų vienu metu, šios užklausos gali ateiti iš procesų, besisukančių kitame hoste. • Tarp-procesinis bendravimas – tai bendravimas tarp procesų, kurie vykdomi tame pačiame ar skirtinguose hostuose. Šiems procesams reikia komunikuot tarpusavyje. • Tarp-procesinis bendravimas remiasi eile programinių sąsajų, kurios leidžia programuotojui kurti ir valdyti tokiam bendravimui orientuotas programas. • Programinė sąsaja, kuri palaiko komunikacijas tarp procesų, užtikrina galimybę šiems procesams komunikuoti tarpusavyje • Sąsajų programuotojui programuot nereikia. • Sąsaja gali būti realizuojama įvairiais būdais, kiekvienas iš jų turi savus privalumus bei trūkumus. • Vienoje programoje gali būti panaudoti keli tarp-procesinės sąsajos metodai. Nijolė Sarafinienė
Komunikacija tarp procesų • Komunikacija galima nebūtinai tinkle. • Jei procesai sukasi tame pačiame kompiuteryje, jie gali pasinaudoti tam tikromis operacinės sistemos paslaugomis. vart procesas Vart procesas Vart procesas Vart procesas Op sist. branduolys Op sist. branduolys Op sist. branduolys Nijolė Sarafinienė
Galimi šie tarp-procesinės sąsajos realizavimo metodai UNIX • “pipes” ir “named pipes” (vamzdžiai ir įvardyti vamzdžiai) • pranešimų eilės • semaforai • bendrai naudojama atmintis • soketai Nijolė Sarafinienė
Failai: I/O veiksmai, leidimai I/O veiksmai vykdomi skaitant ar rašant tam tikrą duomenų bloką. Failai pradžioje yra atidaromi, baigus veiksmus yra uždaromi. Failo atidarymo metu yra grąžinamas failo deskriptorius, kuris yra sveikas skaičius. Šis skaičius – tai indeksas šio proceso atidarytų failų lentelėje Veiksmai su failais vykdomi naudojant read, write funkcijas. #define SIZE 1024 char buf[SIZE]; src = open(infile, O_RDONLY); dst = creat(outfile, 0777); while ((nread = read(src, buf, SIZE)) != 0) write(dst, buf, nread); Leidimų sistema UNIX: -rwxrwxrwx -rw-r--r-- 1 os other 9 Jan 24 13:55 infile Nijolė Sarafinienė
Vamzdžiai • Vamzdis yra naudojamas baitų srauto persiuntimui viena kryptimi. • Vamzdis yra sukuriamas naudojant komandą “pipe”, kuri grąžina dviejų sveikų skaičių masyvą. • Šie skaičiai – tai du failų deskriptoriai, kurie gali būti naudojami vykdant read, write veiksmus. Nijolė Sarafinienė
write vykdomas šia kryptimi read vykdomas iš šios pusės Vamzdžio sukūrimas: pipe() int pfd[2]; pipe(pfd); write(pfd[1], buf, size); read(pfd[0], buf, SIZE); Nijolė Sarafinienė
fork() ir pipe() Vienas procesas paprastai nenaudoja vamzdžio. Jis naudojamas kai du giminingi procesai nori komunikuoti vienos krypties principu. Vamzdis turi būt sukuriamas prieš sudalant procesą. Procesas kuria naujus procesus- procesus vaikus naudodamas “fork” kreipinį. Šie procesai galės keistis informacija naudodamiesi vamzdžiu. Prieš fork() Nijolė Sarafinienė
Po fork() Nijolė Sarafinienė
Gaunami du rašymo taškai ir du skaitymo taškai. Bet kuris iš procesų gali tiek rašyti į vamzdį, tiek iš jo skaityti. Tiksliam veiksmų nusakymui turi būti nutariama, kuris procesas rašys į vamzdį, o kuris iš jo skaitys. Vienas iš procesų uždaro skaitymo tašką, kitas rašymo tašką (deskriptorių). Nijolė Sarafinienė
Tarkim, tėvo procesas uždaro skaitymo deskriptorių. Vaiko procesas uždaro rašymo deskriptorių. Tėvas rašys į vamzdį, vaikas skaitys. Kai tėvas uždarys ir rašymo deskriptorių, vaiko procesas, bandydamas skaityti toliau, gaus EOF, tai žymės srauto pabaigą, taigi vaikas galės irgi uždaryti skaitymo deskriptorių Nijolė Sarafinienė
#include <stdio.h> #define SIZE 1024 int main(int argc, char **argv) { int pfd[2]; int nread; int pid; char buf[SIZE]; if (pipe(pfd) == -1) { perror("pipe failed"); exit(1); } if ((pid = fork()) < 0) { perror("fork failed"); exit(2); } if (pid == 0) { /* child */ close(pfd[1]); while ((nread = read(pfd[0], buf, SIZE)) != 0) printf("child read %s\n", buf); close(pfd[0]); } else { /* parent */ close(pfd[0]); strcpy(buf, "hello..."); /* include null terminator in write */ write(pfd[1], buf, strlen(buf)+1); close(pfd[1]); } exit(0); } Nijolė Sarafinienė
Pipes -“vamzdžiai” • UNIX “pipe” mechanizmas naudojamas informacijos perdavimui iš vieno proceso kitam. Duomenys siunčiami tik viena kryptimi. “pipe” perduoda vieno proceso išvedimą kitam procesui kaip įvedimo duomenis. Išvedami duomenys yra buferizuojami pakol įvedantis procesas juos paima. Procesai turi būt giminingi. • UNIX shell’o (apvalkalo) atveju “pipe” mechanizmas nusakomas “|”. • Programose “pipe” mechanizmas realizuojamas naudojant sisteminįkreipinį “pipe”. • Norint sudaryti dviejų krypčių komunikacijas tarp procesų turi būti naudojami du vamzdžiai, po vieną kiekvienai krypčiai. • Šio mechanizmo panaudojimą tarp-procesinei komunikacijai riboja tai, kad taip komunikuoti gali vaikų procesai, kurių tėvas bendras. • Pipe atveju duomenų dydis negali būti didesnis nei 4,096 baitai. Nijolė Sarafinienė
Kas tas “pipe” mechanizmas? • Tai vienos krypties komunikavimo mechanizmas, vienas jo galas yra atviras rašymui, kitas skaitymui. • Tėvas-vaikas turi sutarti kuria kryptim keliaus informacija. Nors galima “pipe” naudoti siuntimui ir viena ir kita kryptim, tačiau tokia komunikacija yra komplikuota. • Esant reikalui tėvas gali sukurti du “pipe” mechanizmus, juos naudojant atskira kryptimi. • “pipe” – tai srautinio komunikavimo mechanizmas, t.y. visi siunčiami pranešimai sudedami iš eilės ir patikimai persiunčiami. Jei skaitant iš “pipe” pareikalaujamas tam tikras baitų kiekis, tai jis išskiriamas iš srauto – atėjęs jis gali būti per vieną ar kelis write() kreipinius. Nijolė Sarafinienė
UNIX shell naudoja pipePav: who | sort | lpr who process sort process lpr process write fd write fd read fd read fd kernel pipe pipe flow of data flow of data Nijolė Sarafinienė
dup pipe mechanizmas veikia, nes du procesai žino šio vamzdžio abiejų taškų (rašymo ir skaitymo) failų deskriptorius. Kiekvienas procesas turi standartinius deskriptorius: stdin (0), stdout (1) ir stderr (2). Sekančių failų deskriptorių reikšmės priklauso nuo to, kiek yra atidarytų failų ir gali būti pavyzdžiui 3 ar 4. Negiminingi procesai, net ir procesai, kurie keičia egzistuojantį procesą per exec f-jas nežino, kurie deskriptoriai priklauso vamzdžiui. Nijolė Sarafinienė
Pavyzdys: Kuriamas vamzdis: ``ls | wc'' Shelo procesas irgi turi sukurti vamzdį, o po to vykdyti fork ir kurti kitą procesą. Turi veikti du procesai: ls ir wc Tėvo procesas vykdant exec yra pakeičiamas “ls” procesu, Vaiko procesas, vykdant exec – “wc” procesu Tarkim rašymo į vamzdį deskriptorius yra 4, o skaitymo 3. Komanda ls paprastai rašymui naudoja 1deskriptorių. Komanda wc paprastai skaito iš 0 deskriptoriaus Kaip visa tai suderinama? Nijolė Sarafinienė
ls | wc sh pipe sh pipe sh sh exec exec pipe wc ls Nijolė Sarafinienė
Naudojama ``dup2(d1,d2)'' funkcija, kuri d1 reikšmę sutapatina su d2 reikšme.Tikslinga fd =3 pakeisti į 1, ir fd=4 pakeisti į 0.tada senos fd=3 ir fd=4 nenaudojamos. Nijolė Sarafinienė
Po dup2() Nijolė Sarafinienė
Programos pavyzdys int main(void) { int pfd[2]; pipe(pfd); if (fork() == 0) { /* vaikas */ close(pfd[1]); dup2(pfd[0], 0); close(pfd[0]); execlp("wc", "wc", (char *) 0); } else { /* tevas */ close(pfd[0]); dup2(pfd[1], 1); close(pfd[1]); execlp("ls", "ls", (char *) 0); } } Nijolė Sarafinienė
Įvardyti vamzdžiai • Tai vamzdis su specifiniu vardu. • Juo gali naudotis negiminingi procesai. • Pranešimą, nusiųstą į šio tipo vamzdį gali skaityti bet koks autorizuotas procesas, kuris žino įvardyto vamzdžio vardą. • Įvardyti vamzdžiai kartais vadinami FIFO, kadangi tie duomenys, kurie pirmi buvo įrašyti į vamzdį, pirmi ir bus nuskaityti. Nijolė Sarafinienė
FIFO • FIFO (First in, First Out) mechanizmas yra panašus į pipe • Srautas vienos krypties • Pirmas įrašytas baitas ir skaityme bus pirmas • Priešingai nei pipe, FIFO turi su juo susijusį vardą • Sukuriama mknod sisteminiu kreipiniu (jis paprastai yra skiriamas supervartotojui ir naudojamas kuriant naują įrenginį , tačiau kiti vartotojai šiuo kreipiniu gali kurti FIFO). ignoruojama FIFO atv int mknod (char *pathname, int mode, int dev); Nijolė Sarafinienė
FIFO • Sukūrus FIFO, jis turi būti atidaromas skaitymui arba rašymui… • Yra trys sisteminiai kreipiniai, tam kad sukurti FIFO ir atidaryti jį skaitymui ir rašymui, kai tuo tarpu vienas pipe sisteminis kreipinys darė tą patį. • Normaliai, FIFO atidarymas (open) vien skaitymui (read) be rašančių procesų, ar FIFO atidarymas rašymui be skaitančių procesų yra blokuojantys sisteminiai kreipiniai. • O_NDELAY opcija yra naudojama blokavimui nuimti… • Jei rašymo į FIFO ar PIPE dydis yra mažesnis nei FIFO ar pipe dydis(4,096 B), tai yra garantuojama, kad šis veiksmas yra nepertraukiamas ( atomic). Rašymo ir skaitymo funkcijos nekinta:read,write Nijolė Sarafinienė
FIFO #include <sys/types.h> #include <sys/stat.h> #include <sys/errno.h> extern int errno; #define FIFO1 “/tmp/fifo.1” #define FIFO2 “/tmp/fifo.2” #define PERMS 0666 main() { int childpid, readfd, writefd; if ( (mknod(FIFO1, S_IFIFO|PERMS, 0)<0) && (errno!=EEXIST) ) err_sys (“Can’t create fifo 1: %s”, FIFO1); if ( (mknod(FIFO2, S_IFIFO|PERMS, 0)<0) && (errno!=EEXIST) ) { unlink (FIFO1); err_sys (“Can’t create fifo 2: %s”, FIFO2); } if ( (childpid=fork()) < 0 ) sys_err (“can’t fork”); Iš <sys/stat.h> specifikuojant FIFO Kuri yra kuriama Nijolė Sarafinienė
FIFO else if (childpid>0) { /* parent */ if ( (writefd = open(FIFO1, 1)) < 0 ) err_sys (“Parent: can’t open write fifo”); if ( (readfd = open(FIFO2, 0)) < 0 ) err_sys (“Parent: can’t open read fifo”); client (readfd, writefd); while (wait((int *) 0) != childpid) ; /* wait for child */ close (readfd); close (writefd); if (unlink(FIFO1) < 0) err_sys (“Parent: Can’t unlink %s”, FIFO1); if (unlink(FIFO2) < 0) err_sys (“Parent: Can’t unlink %s”, FIFO2); exit (0); Nijolė Sarafinienė
FIFO } else { /* child */ if ( (readfd = open(FIFO1, 0)) < 0 ) err_sys (“Parent: can’t open read fifo”); if ( (writefd = open(FIFO2, 1)) < 0 ) err_sys (“Parent: can’t open write fifo”); server (readfd, writefd); close (readfd); close (writefd); exit (0); } } Nijolė Sarafinienė
FIFO • Siekiant išvengti mirties taško yra svarbi eilės tvarka, kuria yra vykdomi open kreipiniai kliento bei serverio dalyje!… • Arba galima pasinaudoti O_NDELAY alternatyva • Naudojant FIFO, gali būti naudojamos dvi skirtingos programos/procesai, kurie nebūtinai eina iš vieno tėvo ir yra atsiradę per fork() kreipinį. Nijolė Sarafinienė
FIFO • Tiek pipe, tiek FIFO atveju siunčiami duomenys yra interpretuojami kaip ištisinis baitų srautas, į jo struktūrą persiuntimo metu nėra kreipiamas dėmesys. • Skaitantis procesas, skaitydamas 100B, negali pasakyti ar tie baitai įrašyti per vieną ar kelis write veiksmus, vieno – ar kelių procesų. • Pačios aplikacijos turi susitarti dėl duomenų, kuriais yra keičiamasi struktūros. Nijolė Sarafinienė
msgget() semget() shmget() char *path key_t key int id ftok() char proj int flag Visais šiais atvejais pradžioje yra sugeneruojamas tarpprocesinio komunikavimo raktas, kurio tipas yra key_t, ir kuris yra sukuriamas vienareikšmiškas, jei nurodomi tokie patys argumentai System V IPC • Pranešimų eilės • Semaforai • Dalinamasi atmintis #include <sys/types.h> #include <ipc.h> key_t ftok (char *pathname, char proj); Pathname yra nuoroda į failą, project ID dydžiu galima nurodyti vyriausią rakto (key) baitą ir naudoti sekančius baitus kaip eilės numerius. Rakto reikšmė yra naudojama tiek veiksmuose su pranešimų eilėmis, tiek veiksmuose su semaforais, tiek su dalinamasi atmintimi. Nijolė Sarafinienė
Pranešimų eilė (Message queuing) Programavime procesai gali naudoti “message queueing” mechanizmą norėdami perduoti duomenis ar pasikeisti duomenimis per sistemos valdomas pranešimų eiles. Pranešimai gali būt įvairaus tipo , jie gali būt įvairiai panaudojami. • Pranešimų eilė gali būti sukurta vieno proceso ir naudojama daugelio procesų, kurie skaito/rašo pranešimus. • Pavyzdžiui serverio procesas gali skaityti ar rašyti pranešimus į pranešimų eilę, skirtą kliento procesui. Pranešimo tipas gali būti panaudojamas pranešimo surišimui su atitinkamu kliento procesu net jei visi pranešimai yra vienoje eilėje. • Pranešimų eilę tvarko sistemos branduolys. Aplikacijų programos (jų procesai) sukuria pranešimų eiles ir siunčia į jas pranešimus arba gauna iš jų pranešimus naudodamos aplikacinių programų sąsają (API) • UNIX sistemoje C kalbos f-ja msgget su įvairiais parametrais yra naudojama nusakant kokius veiksmus reikia atlikti, su kokia pranešimų eile ir ... • Maksimalus pranešimo ilgis eilėje yra ribojamas operacinės sistemos ir paprastai jis yra <=8,192 baitų. Nijolė Sarafinienė
Pranešimų eilės • Kliento-serverio modelis naudojant dvi pranešimų eiles: #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <sys/errno.h> extern int errno; #define MKEY1 1234L #define MKEY2 2345L #define PERMS 0666 Nijolė Sarafinienė
Pranešimų eilės • Serveris main() { int readid, writeid; /* create message queues if required */ if ( (readid=msgget(MKEY1, PERMS|IPC_CREAT)) < 0 ) err_sys (“Server: Can’t get message queue 1”); if ( (writeid=msgget(MKEY2, PERMS|IPC_CREAT)) < 0 ) err_sys (“Server: Can’t get message queue 2”); server (readid, writeid); exit(0); } Nijolė Sarafinienė
main() { int readid, writeid; /* open message queues, server must have already created them */ if ( (writeid=msgget(MKEY1, 0)) < 0 ) err_sys (“Client: Can’t get message queue 1”); if ( (readid=msgget(MKEY2, 0)) < 0 ) err_sys (“Client: Can’t get message queue 2”); client (readid, writeid); /* delete message queues */ if (msgctl(readid, IPC_RMID, (struct msqid_ds *)0)<0) err_sys (“Client: Can’t RMID message queue 1”); if (msgctl(writeid, IPC_RMID, (struct msqid_ds *)0)<0) err_sys (“Client: Can’t RMID message queue 2”); exit(0); } • Klientas Nijolė Sarafinienė
Klientas ir serveris naudojasi sekančiomis funkcijomis: msgsnd-pranešimų siuntimas • msgrcv- pranešimų priėmimas msg_send (int id, Mesg *mesgptr) { if (msgsnd(id, (char *) &(mesgptr->mesg_type), mesgptr->mesg_len , 0)!=0) err_sys (“msgsnd error”); } int msg_recv (int id, Mesg *mesgptr) { int n; n = msgrcv(id, (char *) &(mesgptr->mesg_type), MAXMESGDATA , mesgptr->mesg_type, 0); if ( (mesgptr->mesg_len=0) < 0 ) err_sys (“msgrcv error”); return (n); /* n to be 0 at the end of the file */ } Nijolė Sarafinienė
semaforai • Jie naudojami siekiant išspręsti sinchronizacijos problemas. • Programuojant UNIX aplinkoje semaforai yra naudojami sprendžiant sinchronizavimo bei koordinavimo problemas, kurios atsiranda kai keletas procesų varžosi dėl tų pačių operacinės sistemos resursų. • Semaforai įgyja sveikas teigiamas arba lygias 0 reiksmes. Jie saugomi operacinės sistemos atmintyje,kiekvienas procesas gali juos patikrinti bei pakeisti. Priklausomai nuo to kokią semaforo reikšmę procesas randa, jis gali naudotis atitinkamu resursu arba resursas yra užimtas ir procesas turi palaukti kažkiek ir po to vėl bandyti tikrinti semaforo reikšmę. • Semaforai pagrinde naudojami dviem tikslais: • dalantis bendra atminties erdve arba • dalantis priėjimu prie failų. • Semaforai yra viena iš priemonių realizuojant tarp-procesines komunikacijas. C kalba turi atitinkamas funkcijas, skirtas veiksmams su semaforais. Nijolė Sarafinienė
Bendrai naudojama atmintis • Leidžiama keistis duomenimis naudojant tam išskirtą sritį. Semaforai naudojami priėjimo prie šios srities reguliavimui. • bendrai naudojama atmintis – tai metodas, kuriuo naudodamiesi programų procesai gali keistis duomenimis greičiau nei naudodami skaitymą/rašymą per operacinės sistemos servisus. Pavyzdžiui, klientinis procesas gali norėti perduoti duomenis serverio procesui, serverio procesas juos modifikuos ir grąžins kliento procesui. • Paprastai tai reikalauja, kad klientas rašytų į išvedimo failą (naudojamas operacinės sistemos buferis) ir serveris skaitytų šį failą iš buferio į savo darbinę sritį. Naudojant išskirtą bendro naudojimo sritį duomenys tampa tiesiogiai prieinamais abiems procesams • Norint įdėti duomenis į bendrą sritį, klientinis procesas gauna priėjimą prie šios srities patikrindamas semaforo reikšmę, įrašo duomenis, bei suaktyvina semaforą pranešdamas serveriui ( kuris periodiškai tikrina šią atmintį ieškodamas įvedimo) , kad duomenys laukia. Serveris iš savo pusės, pakeitęs – modifikavęs duomenis įrašo juos atgal į bendrai naudojamą atmintį ir naudoja semaforą pranešdamas apie tai, kad duomenys yra paruošti. Nijolė Sarafinienė
Bendrai naudojama atmintis Bendrai naudojama atmintis – tai tam tikra atminties dalis adresinėje erdvėje, kuri gali būti adresuojama iš dviejų ar daugiau procesų. Jei vienas procesas padaro pakeitimus šioje atmintyje, tai tai atsispindi abiems procesams. Pavyzdys: #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> int shmget(key_t key, int size, int shmflg); char *shmat(int shmid, char *shmaddr, int shmflg); int shmdt(char *shmaddr); Nijolė Sarafinienė
shmgetyra naudojama sukuriant bendrai naudojamą atmintį. Ši atmintis yra identifikuojama raktu, kuris yra sveikas skaičius ir dėl kurio susitaria visi procesai, kurie naudosis šiuo atminties gabalu. Jie gali nustatyti tokios atminties dydį ir leidimus (pav: -rwx------). shmatima bendrai naudojamos atminties identifikatorių ir jį atvaizduoja į šio proceso adresinę erdvę, grąžindamas nuorodą į ją. Nuo to momento ši nuoroda gali būt naudojama kaip bet kuri nuoroda į atmintį. shmdtatskiria šią sritį nuo proceso adresinės erdvės. Nijolė Sarafinienė
Example:This program forks, creates shared memory on one side and just uses it on the other. The creating side writes the alphabet into this and the other side reads it #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> int main(void) { int shmid; char *shmPtr; int n; if (fork() == 0) { sleep(5); shmid = shmget(2041, 32, 0); if (shmid == -1) exit(1); shmPtr = shmat(shmid, 0, 0); if (shmPtr == (char *) -1) exit(2); for (n = 0; n < 26; n++) putchar(shmPtr[n]); putchar('\n'); } else { shmid = shmget(2041, 32, 0666 | IPC_CREAT); if (shmid == -1) exit(1); shmPtr = shmat(shmid, 0, 0); if (shmPtr == (char *) -1) exit(2); for (n = 0; n < 26; n++) shmPtr[n] = 'a' + n; for (n = 0; n < 26; n++) putchar(shmPtr[n]); putchar('\n'); wait(NULL); shmdt(shmid); } exit(0); } Nijolė Sarafinienė
Soketai • Šis metodas pagrinde naudojamas komunikacijųpalaikymui tinkle. • Palaikomas ryšys tarp serverio ir kliento aplikacijų. • Soketai yra apibrėžiami kaip galiniai komunikavimo taškai. • Soketai yra sukuriami ir naudojami naudojant programines užklausas – f-jas (API – aplikacijų programinė sąsaja). • Soketai gali būti naudojami komunikavimui palaikyti tarp procesų, kurie sukasi ir tame pačiame kompiuteryje. Nijolė Sarafinienė
include <sys/types.h>#include <sys/socket.h>#include <stdio.h>#define DATA1 "In Xanadu, did Kublai Khan . . .“#define DATA2 "A stately pleasure dome decree . . .“ main(){ int sockets[2], child; charbuf[1024]; if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) < 0) { perror("opening stream socket pair"); exit(1); } if ((child = fork()) == -1) perror("fork"); else if (child) { /* This is the parent. */ close(sockets[0]); if (read(sockets[1], buf, 1024, 0) < 0) perror("reading stream message"); printf("-->%s\n", buf); if (write(sockets[1], DATA2, sizeof(DATA2)) < 0) perror("writing stream message"); close(sockets[1]); } else { /* This is the child. */ close(sockets[1]); if (write(sockets[0], DATA1, sizeof(DATA1)) < 0) perror("writing stream message"); if (read(sockets[0], buf, 1024, 0) < 0) perror("reading stream message"); printf("-->%s\n", buf); close(sockets[0]); }} Figure :Use of a socketpair Nijolė Sarafinienė
socketpair() • Galima gauti porą surištų galinio komunikavimo taškų dvipusei srautinei komunikacijai pasinaudojus kvietinį • socketpair(). • socketų pora yra tiesiog “pipe” mechanizmo išplėtimas • Jas galima naudoti tik UNIX domene. The UNIX domenas naudoja įprastus UNIX kelių vardus soketų įvardijimui. Nijolė Sarafinienė