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:

Dane wyjściowe: 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.