Do spisu treści tematu 6
6.5.8 Łącze nienazwane
Łącza nienazwane (pipe), to takie łącza, poprzez które mogą porozumiewać
się jedynie procesy pokrewne. W dokładności, dostęp do danego łącza mogą
dzielić: proces oraz jego potomkowie. Wynika to faktu, że procesy te dziedziczą
deskryptory plików, zas łącza nienazwane są właśnie o nie oparte. Typowy
algorytm korzystania z łącza wygląda następująco:
-
proces tworzy łącze komunikacyjne za pomocą funkcji pipe
-
za pomocą funkcji fork tworzy proces(y) potomny(e)
-
proces macierzysty(lub jeden z potomnych) zamyka koniec łącza slużący
do czytania lub pisania (zależnie od przeznaczenia)
-
jakiś proces potomny zamyka koniec łącza odpowiednio do pisania lub czytania
Dla łącza nienazwanego można wykonać funkcję pipe
która je tworzy. Na deskryptorach łącza możemy wykonywać funkcje read i
write, ioctl, select.
Kod + Opis działania funkcji pipe:
int do_pipe(int *fd)
// dwuelementowa tablica deskryptorów,
[0 ] - czytanie. [1 ] - pisanie
{
struct inode * inode; // i-węzeł powiązany z łączem
struct file *f1, *f2; // wskaźniki do pozycji w tablicy plików
int error;
int i,j;
error = ENFILE;
f1 = get_empty_filp();
if (!f1)
goto no_files;
f2 = get_empty_filp();
if (!f2)
goto close_f1;
-
// znajdź wolne pozycje w tablicy
plików dla łącza
inode = get_pipe_inode();
if (!inode)
goto close_f12;
-
// pobierz z systemu nowy i-węzeł
dla łącza
error = get_unused_fd();
if (error < 0)
goto close_f12_inode;
i = error;
error = get_unused_fd();
if (error < 0)
goto close_f12_inode_i;
j = error;
-
// znajdź dwie wolne pozycje w tablicy
deskryptorów procesu
// oraz przydziel je łączu,
jeden do pisania, drugi do czytania
// wiąże się to z koniecznością
ustawienia odpowiednich flag
f1->f_inode = f2->f_inode = inode;
/* read file */ // ten do czytania (wyłącznie)
f1->f_pos = f2->f_pos = 0;
f1->f_flags = O_RDONLY;
f1->f_op = &read_pipe_fops;
f1->f_mode = 1;
/* write file */ // ten do pisania (wyłącznie)
f2->f_flags = O_WRONLY;
f2->f_op = &write_pipe_fops;
f2->f_mode = 2;
current->files->fd[i] = f1;
current->files->fd[j] = f2;
fd[0] = i;
fd[1] = j;
-
// zainicjuj znalezione pozycje
w tablicy deskryptorów
// oraz tablicę użytkownika
return 0;
// obsluga sytuacji awaryjnych
close_f12_inode_i:
put_unused_fd(i); // oddaj deskryptor
close_f12_inode:
inode->i_count--;
iput(inode); // oddaj i-węzeł
close_f12:
f2->f_count--;
close_f1:
f1->f_count--; // oddaj pozycje w tablicy plików
no_files:
return error;
}
Inne funkcje działające na pipe'ach
Oczywiście łącze ma swoją implementacje funkcji read, write itp, z ktorych
korzystają funkcje API. Dosyć ciekawa jest funkcja lseek:
static long long pipe_lseek(struct inode * inode, struct file *
file, long long offset, int orig) {
}
Funkcja wygląda w ten
sposób, gdyż operacja lseek nie jest na łączu dozwolona. Funkcja zwraca
zawsze błąd.
Biliografia:
Autor: Marcin Polak