FIFO înseamnă că procesele citesc datele în aceeasi ordine în care a fost scrisă.
Sistemul se asigură că datele nu se pierd la mijloc (unul dintre procese iese prematur).
Odată citită din pipe data este ştearsă din pipe, eliberând astfel spatiu pentru procesul care
scrie în pipe.
Un pipe nenumit este o conductă de date care transfera datele între procesele
înrudite (exemplu: între procesul tată şi fiu). Nu suportă comunicaţia în retea şi sunt
întotdeauna orientate byte-stream.
Un pipe numit asigură comunicaţia într-un sens sau în ambele între pipe server şi
pipe client. Poate fi folosita sa interacţioneze între procese nu neapărat înrudite pe maşini
diferite, în retea. [3]
Pipe-ul numit mai este întâlnit şi sub denumirea de pipe FIFO. Numele unui pipe
numit este de fapt un fişier în sistemul de fişiere. Pipe-urile numite sunt vizibile cu
comanda ls ca orice alt fişier cu câteva diferenţe:
% ls -l fifo1
prw-r--r-- 1 mconstan e214 0 May 22 20:15 fifo1|
Litera p din stânga indică faptul că fifo1 este un pipe, deasemenea caracterul | din
coloana dreaptă.
Pe sistemele Linux mai vechi pipe-urile numite se creau prin comanda mknod. Pe
sistemele moderne acest lucru se face prin comanda mkfifo ce primeşte unul sau mai
multe nume de fişiere ca argumente şi creează pipe-uri cu aceste nume. De exemplu
pentru a crea un pipe numit cu numele pipe1 se dă comanda:
mkfifo pipe
Pentru a evidenţia cum lucrează un pipe numit se execută în console separate comenzile :
ls -l > pipe
cat < pipe
Moştenirea handler-ului determină procesul fiu să aibă intrările pentru toate handler-urile
mostenibile (care sunt deschise) în propria sa tabelă obiect. Odată ce valoarea handler-
ului este trimisă fiului printr-un mecanism IPC, acesta poate folosi de asemenea
handlerul. [3]
2
1.3. Comunicare în ambele sensuri folosind pipe-uri
În sisteme mai complexe, se descoperă că comunicarea într-un sens este prea limitată. Se
doreşte astfel să se comunice în ambele sensuri: de la tată la fiu şi de la fiu la tată. Acest
lucru se face relativ uşor folosind două pipe-uri, câte una în fiecare sens. Insă acest mod
poate duce la apariţia unei situaţii numită deadlock (blocare).
Deadlock-ul reprezintă o situaţie în care un grup de două sau mai multe procese aşteaptă
pentru un set de resurse care care sunt alocate altor procese din acelasi grup, ori după
evenimente care trebuie anuntate de alte procese din grup.
Aceasta situaţie poate fi întâlnită atunci când două procese comunică prin 2 pipe-uri. Sunt
prezentate 2 posibile scenarii:
Fiecare pipe are un buffer limitat asociat. Când un proces scrie în pipe, datele sunt
plasate în bufferul pipe-ului, până când este citit de procesul care citeste. Daca
bufferul este plin, apelul de sistem write(),se blocheaza pana se elibereaza
bufferul. Singura cale de eliberare este de a citi din buffer. Astfel daca ambele
procese scriu date, fiecare în capătul pipe-ul lui de scriere, ambele se vor bloca pe
apelul de sistem write(). Cum nici un alt proces nu mai citeste din pipe-uri, cele 2
procese vor intra într-o stare de deadlock. [1]
1.4. Exemple
NAME
SYNOPSIS
#include <unistd.h>
3
int pipe(int filedes[2]);
DESCRIPTION
pipe creates a pair of file descriptors, pointing to a pipe inode, and places them in the
array pointed to by filedes. filedes[0] is for reading, filedes[1] is for writing.
RETURN VALUE
ERRORS
CONFORMING TO
SEE ALSO
REFERENCED BY
csh(1), event(3), fifo(4), fstat(2), ksh(1), lstat(2), pdksh(1), popen(3), stat(2), syscall(2),
syscalls(2), tcsh(1) [5]
Un exemplu simplu de folosire a unui pipe nenumit (sau pipe anonim) sub Linux este
comanda:
ls | grep x
4
mkfifo pipe
ls -l > pipe
cat < pipe
int main()
{
int pfds[2];
char buf[30];
Vom folosi alt exemplu. Intâi procesul tata va crea un fiu. Vom apela fork(). Astfel fiul
va putea să trimită date spre capătul de scriere al pipe-ului, iar tatal le va primi la capătul
de citire astfel:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
int pfds[2];
char buf[30];
pipe(pfds);
if (!fork()) {
printf(" CHILD: writing to the pipe\n");
write(pfds[1], "test", 5);
5
printf(" CHILD: exiting\n");
exit(0);
} else {
printf("PARENT: reading from pipe\n");
read(pfds[0], buf, 5);
printf("PARENT: read \"%s\"\n", buf);
wait(NULL);
}
}
În acest caz tatal încearcă sa citească din pipe înainte ca fiul să scrie în ea. Când acest
lucru se întâmplă, tatal trece în block sau sleep pâna urmeaza ca să sosească date pentru
citire. Tatăl încearcă să citească, trece în sleep, fiul scrie şi iese, tatăl se trezeste şi citeste
datele.
Exerciţiul 1:
Rezolvare:
Se vor folosi apelurile exec() şi dup(). Familia exec de funcţii înlocuieşte procesul curent
ce rulează cu orice proces îi este trimis de exec(). Acesta este funcţia care va fi folosită
pentru a executa ls şi wc –l. Apelul dup() primeste un descriptor de fisier şi îi face o copie
(clonă). Astfel se conectează stdout al comenzii ls cu stdin al comenzii wc. Iesirea stdout
a lui ls intră în pipe şi intrarea stdin alui wc intră în pipe.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
int pfds[2];
pipe(pfds);
if (!fork()) {
close(1); /* close normal stdout */
dup(pfds[1]); /* make stdout same as pfds[1] */
close(pfds[0]); /* we don't need this */
6
execlp("ls", "ls", NULL);
} else {
close(0); /* close normal stdin */
dup(pfds[0]); /* make stdin same as pfds[0] */
close(pfds[1]); /* we don't need this */
execlp("wc", "wc", "-l", NULL);
}
}
Observaţie:
Orice proces cu permisiuni adecvate poate mai apoi citi sau scrie întru-un pipe numit.
Pentru a deschide un pipe numit fară a-l bloca, apelul open(2) însumează masca
O_NDELAY ( din sys/fcntl.h) cu masca modului fişier selectat folosind booleanul sau
operaţia pe apelul open(2). Dacă nici un alt proces nu este conectat la pipe când open(2)
este apelat, se returnează -1 cu errno setat pe EWOULDBLOCK.
1.5. Concluzii
Probabil că modul cel mai bun de folosire al pipe-ului este cel mai banal: trimiterea
stdout al unei comenzi la stdin-ul alteia. Pentru alte moduri de folosire, pipe-urile sunt
destul de limitate, existând alte tehnici IPC mai avantajoase.
7
Bibliografie