Lacza komunikacyjne sa najprostszym sposobem do przekazywania
danych miedzy procesami. Dane przekazywane sa zgodnie z zasada
kolejki prostej (FIFO). Lacza dzielimy na dwa rodzaje: nazwane
(kolejki FIFO) i nienazwane (ang. pipe). Dostep do laczy nienazwanych
moga wspoldzielic tylko procesy pokrewne, tzn. Potomkowie procesu,
ktory wywolal funkcje pipe wlacznie z nim samym (dzieki
dziedziczeniu deskryptorow).
Typowy scenariusz korzystania z laczy nienazwanych wyglada nastepujaco:
Lacze nienazwane przechowywane jest w zwyklym i-wezle. Roznica
jest jedynie wartosc pola i_pipe
ustawiona na 1 oraz
u
, w ktorym przechowywana jest struktura pipe_inode_info
(znajduja sie w niej wszystkie informacje potrzebne do korzystania
z lacza oraz bufor na dane, dzieki temu rozne procesy korzystaja
z tych samych wskaznikow do lacza tzn. miejsce, w ktorym zaczynaja
sie dane w buforze lacza).
W pliku include/linux/limits.h
zdefiniowane jest
ograniczenie na wielkosc bufora na przechowywane dane:
#define PIPE_BUF 4096 /* max rozmiar bufora dla lacza (w bajtach) */
pipe_inode_info
Oto dokladna definicja struktury pipe_inode_info
z pliku include/linux/pipe_fs_i.h
:
struct pipe_inode_info { struct wait_queue * wait; /* kolejka dla procesow,ktore chca pisac do pelnego lacza oraz tych, ktore chca czytac z pustego lacza */ char * base; /* wskaznik do bufora danych */ unsigned int start; /* poczatek danych w buforze */ unsigned int len; /* dlugosc danych (w bajtach)*/ unsigned int lock; /* blokada lacza */ unsigned int rd_openers; /* ilosc czytelnikow, ktorzy otworzyli lacze (tylko dla lacza nazwanego) */ unsigned int wr_openers; /* ilosc pisarzy, ktorzy otworzyli lacze (tylko dla lacza nazwanego) */ unsigned int readers; /* ilosc czytelnikow */ unsigned int writers; /* ilosc pisarzy */ };
Do obslugi laczy procesy uzywaja zwyklych funkcji stosowanych
do plikow, takich jak read
, write
i
close
. Aby utworzyc lacze nienazwane i tym samym
je otworzyc nalezy uzyc funkcji pipe
.
pipe()
- sluzy do tworzenia lacza nienazwanego.
Przed wywolaniem funkcji nalezy wczesniej zarezerwowac miejsce dla argumentu fd.
DEFINICJA: int pipe(int fd[2]) WYNIK: 0 w przypadku sukcesu oraz w tablicy dwuelementowej fd pierwszym elementem jest deskryptor do czytania a drugim deskryptor do pisania -1, gdy blad: errno = EMFILE (za duzo deskryptorow jest w uzyciu przez proces) ENFILE (brakuje miejsca w systemowa tablica plikow) EFAULT (zly argument)
A oto jak wyglada algorytm:
{ sprawdzenie poprawnosci parametru fd; przydziel nowy i-wezel z urzadzenia do przechowywania laczy (za pomoca funkcji get_pipe_inode); znajdz dwie wolne pozycje w tablicy plikow i przydziel pierwsza do czytania a druga do pisania (za pomoca funkcji get_empty_filp); znajdz dwie wolne pozycje w tablicy deskryptorow procesu i zainicjuj je, tak by wskazywaly na odpowiednie pozycje w tablicy plikow, podstawiajac od razu odpowiednie wartosci w argumencie fd (fd[0]= deskryptor do czytania, fd[1]= deskryptor do pisania); zainicjuj znalezione pozycje w tablicy plikow, by wskazywaly na nowy i-wezel; ustaw flagi i wskaznik do struktury z operacjami w znalezionych pozycjach w tablicy plikow odpowiednio do czytania i pisania; }
read()
- sluzy do czytania lacza nienazwanego.
Raz przeczytanej informacji nie mozna powtornie odczytac.
DEFINICJA: int read(int fd, char *buf, size_t count) WYNIK: w przypadku sukcesu liczba przeczytanych bajtow (0 jesli nie ma pisarzy i puste lacze) -1, gdy blad: errno = EINTR (funkcja zostala przerwana przez sygnal) EAGAIN (zostala uzyta flaga O_NONBLOCK i lacze bylo puste) EISDIR (fd jest katalogiem) EBADF (fd nie jest deskryptorem) EINVAL (fd nie jest deskryptorem, z ktorego mozna czytac) EFAULT (wskaznik buf jest poza przestrzenia adresowa procesu)
Czytanie danych z lacza przebiega zgodnie z ponizszymi regulami:
write()
- sluzy do pisania do lacza nienazwanego.
DEFINICJA: size_t read(int fd,const char *buf, size_t count) WYNIK: w przypadku sukcesu liczba bajtow zapisanych do lacza -1, gdy blad: errno = EINTR (funkcja zostala przerwana przez sygnal) EAGAIN (zostala uzyta flaga O_NONBLOCK i nie bylo miejsca na wpisanie wszystkich danych) EBADF (fd nie jest deskryptorem) EINVAL (fd nie jest deskryptorem, do ktorego mozna pisac) EFAULT (wskaznik buf jest poza przestrzenia adresowa procesu) EPIPE (nie ma czytelnikow i lacze jest zablokowane lub nie ma w nim miejsca)
Pisanie danych do lacza przebiega zgodnie z ponizszymi regulami:
Jezeli proces chce zapisac wieksza liczbe bajtow niz wynosi
ilosc wolnego miejsca i nie jest ustawiona flaga O_NONBLOCK,
to operacja pisania moze nie byc niepodzielna (po czesci danych
od jednego procesu moze zostac umieszczona czesc danych od drugiego
procesu). W pozostalych przypadkach operacja
pisania jest podzielna.
Jesli komus nie wystarczaja te informacje, to bardziej szczegolowy algorytm
znajdzie w temacie Kolejki FIFO.
include/linux/pipe_fs_i.h
(definicja struktury pipe_inode_info)
fs/pipe.c
(implementacja oraz definicje niektorych struktur)