Operacje na procesach (2)

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.