Do inicjalizacji buforów stron służy funkcja page_cache_init.
Oto ona wraz z moimi komentarzami:
void __init page_cache_init(unsigned long mempages)
/**
* Bufor stron jest inicjalizowany przy starcie systemu.
* Tak więc ta funkcja jest wołana tylko raz w funkcji:
* start_kernel() z parametrem num_physpages, przy czym
* num_physpages = ilość pamięci w systemie wyrażona w ramkach.
*/
{
unsigned long htable_size, order;
htable_size = mempages;
htable_size *= sizeof(struct page *);
/* na i386 jest to równoważne: htable_size *= 16; */
for(order = 0; (PAGE_SIZE << order) < htable_size; order++)
;
/**
* pętla ustawia order tak żeby htable_size mieścił się w 2^order
* stron. Order przyjmie następujące wartości w zależności od
* rozmiaru pamięci:
* pamięć | order | rozmiar tablicy page_hash_table
* 4MB -- 8MB-1B | 3 | 2048 kubełków
* 8MB -- 16MB-1B | 4 | 4096 -- // --
* 16MB -- 32MB-1B | 5 | 8192
* 32MB -- 64MB-1B | 6 | 16384
* 64MB -- 128MB-1B | 7 | 32768
* 128MB -- 256MB-1B | 8 | 65536
* 256MB -- 512MB-1B | 9 | 131072
* 512MB -- 4GB | 9 bo order jest poźniej (przy przydzie-
* | laniu pamięci) przycinany tak, żeby nie
* | przekraczał stałej MAX_ORDER równej 10
*
* Uzależnienie wielkości tablicy page_hash_table od pamięci
* ma na celu, z jednej strony oszczędność pamięci, a z drugiej
* poprawienie właściwości funkcji mieszającej.
*/
do {
unsigned long tmp =(PAGE_SIZE << order) / sizeof(struct page *);
/**
* tmp jest liczbą wskaźników jakie się pomieszczą
* w (PAGE_SIZE << order) bajtach pamięci.
*
* Poniższe operacje wyznaczają logarytm dwójkowy z tmp.
* Jak się potem okaże, tak uzyskana wartość page_hash_bits
* będzie podstawą do wyznaczenia liczby pozycji przechowy-
* wanych w tablicy page_hash_table. Patrz do punktu o
* strukturach danych.
*/
page_hash_bits = 0;
while((tmp >>= 1UL) != 0UL)
page_hash_bits++;
page_hash_table = (struct page **)
__get_free_pages(GFP_ATOMIC, order);
/**
* __get_free_pages zwraca NULL jeśli order >= MAX_ORDER,
* lub gdy nie udało się przydzielić pamięci, wpp. zwraca
* wskaźnik do pierwszej z 2^order ramek pamięci
* przydzielonych na tablicę page_hash_table.
* Przydzielone ramki są powiązane w listę dwukierunkową.
*/
} while(page_hash_table == NULL && --order > 0);
/**
* w printk jest mały BŁĄD, bo przez wzgląd na warunek
* ostatniej pętli powinno być (order + 1)
*/
printk(
"Page-cache hash table entries: %d (order: %ld, %ld bytes)\n"
,(1 << page_hash_bits), order, (PAGE_SIZE << order));
/**
* Tak więc w tablicy page_hash_table będziemy mieć:
* (1 << page_hash_bits) pozycji!
*/
if (!page_hash_table)
panic("Failed to allocate page hash table\n");
memset((void *)page_hash_table, 0,
PAGE_HASH_SIZE * sizeof(struct page *));
}
Tomasz Szymko 25 listopada 2001