Moduł do obsługi podręcznej pamięci buforowej w systemie Linux korzysta z tych samych stron pamięci, co pozostałe procesy. Zasadniczą jego cechą jest to, że na buforowanie bloków dyskowych pobiera tyle pamięci, ile jest aktualnie dostępne (z drobnym tylko ograniczeniem).
Dokładniej: jeśli zajdzie potrzeba na buforowanie bloku dyskowego, którego nie ma jeszcze w pamięci buforowej, a lista buforów ,,wolnych'' będzie pusta, to pierwszym krokiem systemu będzie próba zarezerwowania nowej strony pamięci (funkcja refill_freelist).
Strategia taka prowadzi do zajęcia bardzo dużej części pamięci przez pamięć buforową. Jeśli inne procesy zgłoszą zapotrzebowanie na pamięć, to zachodzi potrzeba zwolnienia stron z użytkowania przez bufory. System musi poświęcić na to pewną ilość czasu.
Zachodzi pytanie, czy strategia stosowana w Linuxie jest zawsze korzystna. Może lepiej byłoby ograniczyć pamięć, którą mogą wypełnić bufory.
Niech ,,trafienie'' oznacza wywołanie funkcji getblk, dla którego żądany blok znajduje się już w pamięci. Skuteczność podręcznej pamięci buforowej możemy mierzyć ilością trafień w stosunku do ogólnej liczby wywołań funkcji getblk.
Jeżeli procent trafień zależy liniowo od pamięci przeznaczonej na pamięć buforową, to oczywiście ograniczenie tej pamięci zawsze będzie wiązać się z pogorszeniem efektywności systemu:
Jeżeli jednak narastanie nie jest liniowe, ale np. takie:
to obcięcie pamięci przeznaczonej na buforowanie na poziomie np. p0 (zaznaczonym linią przerywaną) nie powinno osłabić zbytnio efektu buforowania, a rzadziej trzeba by było zwalniać strony zajmowane przez bufory.
Oczywiście badanie procenta trafień powinno odbywać się przy jakimś ustalonym użytkowaniu systemu, tzn. przy działaniu tych samych programów w tym samym przedziale czasu.
Tematem zadania jest:
a) Zmodyfikowanie modułu odpowiedzialnego za podręczną pamięć buforową tak, aby ilość dostępnej dla niego pamięci można było ograniczyć przez stałą;
b) Napisanie procedury wyświetlającej aktualny stan pamięci buforowej - np. poprzez rozszerzenie już istniejącej show_buffers. Procedura taka powinna wyświetlać:
procent trafień w ustalonym przedziale czasu,
ilość buforów na każdej z list lru,
ilość buforów, które znajdują się na nieodpowiedniej liście lru (tzn. innej niż wskazuje to pole nagłówka b_list)
c) Przeprowadzeniu eksperymentu prowadzącego do wyliczenia zależności procenta trafień od ograniczenia pamięci
Podpunkt a) powinien być zrealizowany tak, aby umożliwiać zmianę ograniczenia pamięci z poziomu użytkownika, tzn. bez ponownej kompilacji jądra.
Wskazówki:
1. Jak umożliwić przesyłanie parametrów do działającego systemu:
Można to oczywiście zrobić na wiele sposobów, ten opisany poniżej jest chyba najprostszy, choć nieelegancki. Przesyłanie danych nie jest jednak głównym tematem zadania.
Jedną z funkcji, którą udostępnia moduł obsługujący pamięć buforową jest fsync, która wymusza zapisanie pliku na dysk. Taki jest jej nagłówek:
asmlinkage int sys_fsync(unsigned int fd);
Argument fd jest numerem deskryptora, więc jest zawsze mniejszy niż 20. Proponuję, aby dla wartości większych od 20 funkcja wykonywała jakąś nową (naszą) procedurę. Początek funkcji sys_fsync mógłby wyglądać tak:
asmlinkage int sys_fsync(unsigned int fd) { if (fd>;20) { zrób_coś_nowego(fd); return NULL; }; ... }
Po skompilowaniu i uruhomieniu tak wyglądającego jądra możemy wywołać funkcję zrób_coś_nowego uruchamiając np. taki program napisany w C:
main() { fsync(123); };
2. Jak wyświetlać informacje dotyczące jądra:
Wywołanie przez jądro procedury:
write_tty_message(current->;tty, "Tekst, np. zmienna typu char* \r\n");
spowoduje wypisanie odpowiedniego napisu na ekranie użytkownika.