Zad.1. (2 punkty - na zajęciach)
Napisz program w ANSI C wykonujący jakąś trywialną operację (np. ++i;)
w nieskończonej pętli. Skompiluj i uruchom program, a następnie programem
top sprawdź, czy Twój program pokazuje się w czołówce programów
wykorzystujących cykle obliczeniowe komputera. Przed przejściem do
dalszych prac zabij program klawiszem Ctrl-C. Dodaj w pętli małe
opóźnienie (sleep(1);, a najlepiej nanosleep(); z opóźnieniem np. 10
milisekund) i upewnij się, że po uruchomieniu tego programu nie pojawia się
on już na szczycie listy top.
Domyślna częstotliwość odświeżania programu top jest mała, spróbuj ją
zmienić korzystając z dostępnej pomocy programu. Zapisz co należało dodać
do wywołania programu.
Zad.2. (4 punkty - na zajęciach, lub 2 punkty - w domu)
Dodaj w stworzonym programie przechwytywanie sygnału/ów, i wykorzystując
sygnały: SIGALRM, SIGTERM, SIGUSR1, SIGUSR2 wypróbuj następujące
reakcje na sygnał:
(a) całkowite ignorowanie sygnału,
(b) wyświetlenie komunikatu i zakończenie pracy programu,
(c) wyświetlenie komunikatu i powrót do wykonywania programu,
(d) wstrzymywanie odbierania sygnału plus okresowe wznawianie jego
odbierania na krótkie okresy czasu
(na przykład, przed uruchomieniem pętli wstrzymaj odbieranie sygnału, i co 1000 iteracji odblokuj, i natychmiast ponownie wstrzymaj odbieranie tego sygnału, z odpowiednimi komunikatami przed i po odblokowaniu).
W raporcie wklej instrukcje programu deklarujące poszczególne reakcje na sygnał, i podsumuj uzyskane wyniki.
Uwaga1: do wstrzymywania/odblokowania odbierania sygnałów można użyć
funkcji sighold/sigrelse. Na Linuksie kompilacja programów z tymi
funkcjami wymaga zdefiniowania makra _XOPEN_SOURCE z wartością >= 500.
Uwaga2: funkcje signal/sigset/sighold/sigrelse należą do
tradycyjnego interfejsu obsługi sygnałów. Ich użycie jest bardzo proste,
ale mają szereg wad (patrz man signal). Nowoczesny interfejs obsługi
sygnałów składa się z szeregu funkcji z których główną jest sigaction.
Uwaga3: funkcje obsługi sygnałów (tzw. handlery) powinny być pisane w bardzo szczególny sposób. Powinny być minimalne, bardzo krótkie i bardzo niezawodne, aby nie dopuścić do wygenerowania jakiegokolwiek błędu i innego sygnału w trakcie wykonywania handlera. Praktycznie, treść handlera powinna być ograniczona do: wyświetlenia komunikatu o zaistniałej sytuacji, ustawienia wartości zmiennej globalnej, ewentualnych akcji ratunkowych, takich jak zamknięcie zapisywanych plików, i powrotu z handlera, lub zatrzymania programu. Handler nie powinien realizować żadnych funkcji programu.
Zad.3. (2 punkty - w domu)
Zapoznaj się z narzędziami umożliwiającymi odczyt pseudosystemu plików
/proc (man proc). W systemie Solaris pliki w tym systemie mają
specyficzny format, i do ich odczytu i dekodowania treści służy odpowiedni
zestaw programów.
W systemie Linux pliki w /proc maja formaty tekstowe i można je
odczytywać (a w konkretnych przypadkach również zapisywać) zwykłymi
narzędziami do operacji na plikach tekstowych, jak: cat, grep, itp.
Uruchom program z poprzedniego punktu przechwytujący/ignorujący wybrane sygnały. Następnie sprawdź tablicę akcji przypisanych poszczególnym sygnałom dla uruchomionego procesu. W raporcie podaj polecenia wyświetlające informację o obsłudze sygnałów: (a) dla systemu Linux, (b) dla systemu Solaris. W każdym punkcie wklej otrzymane wyniki i krótko wyjaśnij znaczenie wyświetlanych informacji.
Zad.4. (2 punkty - w domu)
Stwórz potok trzech poleceń, tak aby pierwszy program w nieskończonej pętli
wypisywał jakiś tekst. Za pomocą odpowiedniego programu operującego na
strukturze /proc zbadaj otwarte pliki każdego z procesów uczestniczących
w potoku. Czy wyłącznie na podstawie uzyskanych w ten sposób informacji
można odtworzyć kolejność występowania poleceń w potoku? Jeśli tak to w
jaki sposób? W raporcie odpowiedz na te pytania oddzielnie: (a) dla
systemu Linux, (b) dla systemu Solaris.