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.
Podpunkt a) powinien być zrealizowany tak, aby umożliwiać zmianę ograniczenia pamięci z poziomu użytkownika, tzn. bez ponownej kompilacji jądra.
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); };
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.
autor: Tomasz Bogusławski