System plików
Algorytmy czytania bloków - bread i breada
Krzysztof Sikora
1. Wstęp
Funkcja bread (nazwa pochodzi od: block read) jest wywoływana
gdy ma być przeczytany blok dyskowy.
2. Lokalizacja
Algorytm bread znajduje się w pliku fs/buffer.c.
3. Działanie
Nagłówek:
struct buffer_head * bread(kdev_t dev, int block, int size)
Dane wejściowe:
-
dev - urządzenie
-
block - numer bloku
-
size - rozmiar bloku
Dane wyjściowe:
-
funkcja zwraca bufor zawierający żądany blok lub NULL w przypadku gdy bloku
nie udało się odczytać
Ponieważ kod funkcji jest niesłychanie krotki i klarowny umieściłem go
w prezentacji.
struct buffer_head * bread(kdev_t dev, int block, int size)
{
struct buffer_head * bh;
/* znajdź bufor z blokiem */
bh = getblk(dev, block, size);
/* czy jest aktualny */
if (buffer_uptodate(bh))
return bh;
/* rozpocznij czytanie z dysku */
ll_rw_block(READ, 1, &bh);
/* zaczekaj na koniec operacji wejścia/wyjścia */
wait_on_buffer(bh);
/* czy jest aktualny */
if (buffer_uptodate(bh))
return bh;
/* zwolnij bufor */
brelse(bh);
return NULL;
}
Należy zwrócić uwagę na fakt, ze funkcja getblk zawsze zwraca bufor.
Albo zawierający blok (jeśli takowy znajdzie w pamięci) albo pobrany z puli wolnych
buforów (w przeciwnym przypadku). Dlatego na koniec funkcji bread musimy
zwolnić bufor wywołując funkcje brelse.
Rysunek 1: Schemat blokowy algorytmu bread
4. Poprzednie wersje
Od kilku wersji jądra Linuksa kod funkcji bread pozostaje
niezmieniony.
5. Algorytm czytania bloków z wyprzedzeniem - breada
Podczas czytania pliku rzadko zdarza się aby był czytany tylko jeden jego blok.
Dobrym pomysłem jest więc czytanie kilku bloków z wyprzedzeniem.
W jądrze 2.2.x zajmowała się tym funkcja breada (nazwa pochodzi od: block read ahead),
która została usunięta z jądra 2.4.7. Mechanizm jednak pozostał i przeniesiono go na
poziom obsługi konkretnego systemu plików.
Dany system plików definiuje własną strukturę file_operations, której pole read wskazuje na
funkcję desygnowaną do czytania plików. Standardową funkcją umieszczaną tam jest generic_file_read,
jest ona zaimplementowana w pliku mm/filemap.c i to dopiero ona używa funkcji
czytania bloków z wyprzedzeniem - generic_file_readahead. Schemat działania
tej funkcji jest dość skomplikowany i opiera się na
heurystyce zapobiegania wykonywania dużych instrukcji wejścia/wyjścia dla plików,
które nie są tak naprawdę dostępne sekwencyjnie.
W nowszej wersji jądra proces żądający przeczytanie pliku nie jest świadom
czy zostanie przeczytany jeden czy więcej bloków, ponieważ nie używa bezpośrednio
algorytmu czytania bloków z wyprzedzeniem. W poprzednich wersjach trzeba było
jawnie napisać, że chcemy tu i teraz użyć funkcji breada i może
przez to programiści zdecydowali się przenieść ten mechanizm na inny poziom.