flock()
flock()
Funkcja flock()
udostepnia programiscie dostep do drugiego
rodzaju blokady pliku. W Linuxie blokada ta jest umownie nazywana FLOCK
(od nazwy funkcji systemowej). Blokady zakladane sa na caly plik, a nie na
rekord jak w przypadku blokad typu POSIX.
Definicja funcji znajduje sie w pliku fs/locks.c
i ma postac:
int flock(
unsigned int fd /* deskryptor pliku */
unsigned int cmd /* komenda */);
W pliku include/asm/fcntl.h
znajduja sie definicje komend:
#define LOCK_SH 1 /* blokada dzielona */
#define LOCK_EX 2 /* blokada wylaczna */
#define LOCK_NB 4 /* nie usypiaj w czasie blokowania */
#define LOCK_UN 8 /* usuwanie blokady */
Plik nie moze miec jednoczesnie blokad typu dzielonego i wylacznego. Blokada
wylaczna moze byc tylko jedna na jednym pliku, a blokad dzielonych moze byc
wiecej. Najczesciej blokady dzielonej uzywa sie przy czytaniu a wylacznej przy
pisaniu do pliku. Funkcja zwraca 0, jesli zakonczyla sie sukcesem lub ujemna
wartosc bledu.
Implementacja blokad FLOCK jest znacznie prostsza niz w przypadku
blokad typu POSIX, gdyz nie trzeba sprawdzac wszystkich blokad
zalozonych na plik i znajdowac przeciecia z zakladana, a wystarczy sprawdzic
pierwsza zalozona blokade, a wszystkie pozostale beda tego samego typu.
A oto wlasciwy algorytm zakladania i zdejmowania blokad FLOCK:
Algorytm flock_lock_file z pliku fs/locks.c
wejscie: flip strutura file pliku, na ktory zakladamy blokade
caller struktura zawierajaca dane o zakladanej blokadzie
wait czy dozwolone jest usypianie procesu
wyjscie: o jesli sukces lub kod bledu
if (zalozona blokada typu POSIX)
return (-EBUSY);
wez pierwsza blokade na plik;
while (sa jeszcze blokady zalozone)
if (zalozona blokada nalezy do tego samego deskryptora)
{
if (zalozona blokada tego samego typu)
return(0);
zaznacz,ze zmieniamy typ zalozonej blokady;
wyjdz z petli while;
}
if (zmiana typu blokady)
usun zalozona blokade;
if (polecenie usuniecia blokady)
return (0);
etykieta repeat:
wez pierwsza blokade zalozona na plik;
if (blokada POSIX)
return (-EBUSY);
while (sa jeszcze blokady)
{
if (zakladana blokada wywoluje konflikt z zalozona)
{
if (!wait)
return (-EAGAIN);
wstaw blokade na koncu kolejki spiacych na danej blokadzie;
uspij proces na konfliktowej blokadzie;
/* tu juz jestesmy obudzeni */
ubudz inne procesy czekajace na tej samej blokadzie;
goto repeat
}
}
wstaw nowa blokade na kolejke blokad;
return (0);
fork()
exec().
Implikacja tego jest niemoznosc wskazania wlasciciela blokady, a wiec nie mozna
faktycznie wykryc, czy doszlo do zastoju procesow.
include/asm/fcntl.h
(naglowki funkcji, definicje stalych i struktur) include/linux/fs.h
(definicje struktur) fs/fcntl.c
(implementacja
funkcji glownej) fs/locks.c
(implementacja
blokad) Documentation/locks.txt
flock()
byla
realizowana przez odpowiednie odwolanie do fcntl()
.
Czy dalej tak jest?