Twój linuks zawiesza się przy hibernacji?

Zaobserwowałem trudno powtarzalny problem pojawiający się przy próbie zahibernowania linuksa Ubuntu. Nie będę się rozpisywać o zaletach używania hibernacji - dla mnie to bardzo praktyczna opcja pozwalająca skrócić czas “włączania” komputera. Jestem przyzwyczajony do tego, aby natychmiast mieć uruchomione wszystkie programy z których korzystam na co dzień. Problem polegał na tym, że czasami podczas hibernowania system zamiast wyłączyć komputer wyświetlał na ekranie szereg enigmatycznych komunikatów, z których jedyne, co było zrozumiałe to fakt, że coś się zawiesiło. Jedyne co można było zrobić to wcisnąć magiczną kombinację [ALT]+[Print Screen]+[R]+[S]+[I]+[U]+[B] powodującą synchronizację buforów dyskowych, odmontowanie systemu plików i bezpieczny restart (szczegółowy opis tej linuksowej sztuczki jest np. tutaj, odpowiednika w systemie Windows niestety brak)

Stwierdziłem, że nie można tego problemu tak zostawić i zacząłem poszukiwać informacji na temat jego przyczyny. Po drodze trafiłem na fajne alternatywne narzędzia pozwalające na zahibernowanie bądź uśpienie systemu z konsoli: http://en.wikipedia.org/wiki/Uswsusp - polecam. Niemniej jednak również s2disk powodował identyczne zawieszenie się systemu.

Po dłuższych poszukiwaniach udało mi się ustalić, że przyczyną jest bardzo dziwny mechanizm hibernacji stosowany w jądrze linuksa - zupełnie odmienny od tego co jest stosowane w systemie Windows. System linuks zapisuje obraz pamięci do… no właśnie - właściwie na… partycję swap. Nietrudno się domyślić, że gdy swap jest w większości zajęty to nie ma tam miejsca na zapisanie zawartości pamięci fizycznej. Rozwiązanie z oddzielnym plikiem o rozmiarze równym pamięci fizycznej i przeznaczonym wyłącznie do hibernacji w systemie Windows jest o wiele lepsze. Swoją drogą, warto zwrócić uwagę, iż pomimo posiadania dużej ilości pamięci RAM nie warto ograniczać (nie mówiąc już o rezygnacji - słyszałem, że niektórzy użytkownicy tak robią) rozmiaru partycji swap.

Całe szczęście, że jądro linuksa umożliwia określenie dowolnego pliku jako dodatkowej przestrzeni swap. Problem rozwiązałem dodając sobie (trochę na zapas) dodatkowe 3 GiB przestrzeni swap:

dd if=/dev/zero of=/swap3gb bs=1024k count=4000
mkswap /swap3gb                    
swapon /swap3gb                    

Można to w każdej chwili wyłączyć:

swapoff /swap3gb                      
rm /swap3gb

Niestety jak się okazało problemu nie rozwiązałem. Sprawa jest znacznie bardziej skompilowana niż mi się wydawało. Istnieją 2 mechanizmy pozwalające na hibernowanie systemu Linux:

  • Swsusp

  • Tuxonice

Pierwszy z nich jest zaimplementowany w jądrze od wersji 2.6, drugi stanowi łatę na kod jądra i co za tym idzie wymaga jego rekompilacji. Pierwszy z nich jest standardowo używany w systemie i nie obsługuje zapisywania obrazu pamięci przy hibernacji do obszaru swap zdefiniowanego w pliku. Istnieje dość złożony sposób pozwalający na wybudzenie się ze swap’a w pliku polegający na modyfikacji ustawień initfs oraz grub’a. Polega on na odczytaniu fizycznego numeru bloku dyskowego pliku i podania go jako parametr jądra. Szczegółowy opis jest tutaj. Obecnie jestem w trakcie testowania pewnej sztuczki, która być może pozwoli na prostsze rozwiązanie problemu (coś jednak spowodowało, że po dodaniu pliku swap system na kilkadziesiąt hibernacji zawiesił się tylko raz). Jeżeli mój pomysł się sprawdzi oczywiście go opiszę.