Założenia:
· wszystkie programy pisane w ANSI C
· kompilator gcc
· debuger gdb
· do każdego zadania (poza 1) plik makefile
Wstęp teoretyczny:
· Użycie i podstawowe przełączniki kompilatora gcc
· Użycie i podstawowe polecenia debugera gdb
Zadanie:
Bibliotekę kompilujemy do postaci współdzielonej. Program główny stara się ją załadować za pomocą f-cji dlopen i wykorzystać f-cje odnalezione za pomocą dlsym. W przypadku niepowodzenia efektem działania programu jest wyświetlenie jedynie identyfikatorów, w przypadku powodzenia poza identyfikatorami wyświetlane są również nazwy zwrócone przez f-cje biblioteczną. Do zadania należy napisać plik makefile automatyzujący kompilację.
Program wywoływany z jednym argumentem, określającym ilość nowo tworzonych procesów (n). Proces główny tworzy w pętli n nowych procesów. Każdy nowy proces losuje liczbę u z zakresu od 1 do 20, zasypia na u sekund, a następnie kończy się zwracając (exit lub return) kod równy wartości u. W tym czasie proces główny czeka na zakończenie się wszystkich procesów potomnych. Po zakończeniu się każdego procesu potomnego proces macierzysty wyświetla informacje o identyfikatorze zakończonego procesu i jego wylosowanej wartości u (pobranej ze statusu zwróconego przez f-cję wait).
Zwrócić uwagę na to, aby:
Program wywoływany z jednym argumentem określającym plik wejściowy oraz dowolną liczbą dodatkowych argumentów. Każdy argument dodatkowy to pojedynczy znak ASCII. Proces główny ma stworzyć tyle procesów potomnych, ile jest argumentów dodatkowych (czyli jeden proces dla każdego znaku ASCII). Każdy proces potomny zlicza ilość wystąpień zadanego mu znaku ASCII w pliku wejściowym (podanym jako pierwszy argument wywołania programu). Proces potomny po zliczeniu ilości wystąpień znaku w pliku zwraca tą wartość do systemu przez exit bądź return. Po zakończeniu się każdego procesu potomnego proces macierzysty odbiera jego status i wyświetla informacje o każdym znaku podanym jako argument oraz ilości jego wystąpień. Informacje mają zostać wyświetlone przez proces macierzysty!
· Funkcja ftw
Program wywoływany z jednym argumentem określającym katalog. Program ma za zadanie wyświetlić zawartość wskazanego argumentem katalogu w formacie identycznym z wywołaniem polecenia "ls –l –a".
Napisać program, który uruchomi trzy współdziałające procesy. Proces główny
(nazwiemy go procesem I) tworzy proces potomny (który nazwiemy procesem II). Proces II tworzy z kolei swój proces potomny (nazwiemy go procesem III).
Poszczególne procesy mają wykonywać następujące zadania:
– proces III co sekundę wysyła do swojego procesu macierzystego (czyli procesu II) sygnał SIGUSR1. Po 10 wysłanych sygnałach proces III kończy swoje działanie;
– proces II ustawia funkcję obsługi sygnału SIGUSR1 tak, żeby po jego odebraniu na ekranie pojawiła się informacja o tym zdarzeniu (wraz z numerem PID procesu, od którego sygnał dotarł). Co drugi odebrany sygnał SIGUSR1 ma spowodować wysłanie sygnału SIGUSR2 z procesu II do procesu I (czyli w sumie powinno zostać wysłanych 5 sygnałów SIGUSR2, każdy mniej więcej co 2 sekundy). Proces II czeka na zakończenie procesu III, kończy się po odebraniu informacji o jego śmierci.
– proces I ustawia funkcję obsługi sygnału SIGUSR2 tak, żeby po jego odebraniu na ekranie pojawiła się informacja o tym zdarzeniu (wraz z numerem PID procesu, od którego sygnał dotarł). Proces I czeka na zakończenie procesu II, kończy się po odebraniu informacji o jego śmierci.
Dodatkowo program powinien blokować odbiór sygnałów wysyłanych przy naciśnięciu klawiszy Ctrl-Z oraz Ctrl-C.
Modyfikacja programu z zadania 5. Program wywoływany z dwoma argumentami, pierwszy określa katalog, drugi maksymalną ilość zagłębień w podkatalogach (parametr 0 oznacza że wyświetlamy tylko zawartość podanego katalogu, 1 zawartość katalogu i jego bezpośrednich potomków itd.). Program ma za zadanie wyświetlić zawartość wskazanego argumentem katalogu i podkatalogów w formacie identycznym z wywołaniem polecenia "ls –l –a". Dla każdego podkatalogu ma zostać stworzony nowy proces, który uruchomi jeszcze raz ten sam program ze zmienionymi argumentami (inna nazwa katalogu i zmniejszona o 1 głębokość). Procesy powinny się synchronizować tak, aby wyświetlony wynik był czytelny.
Napisać dwa programy współpracujące ze sobą jako serwer i klient. Do komunikacji wykorzystać potoki nazwane (kolejki FIFO). Serwer posiada swój potok, z którego tylko czyta informacje zapisywane przez klientów. Odpowiedzi serwera umieszczane są w unikalnych kolejkach klientów (żeby zapewnić ich unikalność klienci tworzą swoje kolejki na podstawie własnego identyfikatora pid). Poszczególne programy mają wykonywać następujące zadania:
Napisać program liczący wyznacznik macierzy 3x3. Program będzie wywoływany z jednym argumentem, określającym nazwę pliku tekstowego, w którym umieszczona jest macierz. Główny proces czyta plik i umieszcza w pamięci dane o macierzy, tworzy zmienną w której będzie umieszczony obliczony wyznacznik a następnie tworzy dwa wątki. Jeden wątek oblicza według Sarrusa lewe przekątne, drugi prawe przekątne. Obydwa wątki aktualizują zmienną stworzoną przez proces główny. Wynik jest wyświetlany przez proces główny (konieczna jest synchronizacja wątków oraz zabezpieczenie sekcji krytycznej muteksami).
Napisać program będący modyfikacją programu z zadania 8. Serwer i klienci komunikują się za pomocą kolejek komunikatów, a nie potoków. Klienci wywoływani są z dodatkowym parametrem liczbowym, który będzie interpretowany jako typ komunikatu klient-serwer. Obiekt kolejki serwera ma działać na zasadzie kolejki priorytetowej – zgodnie z typem komunikatu klienta. Uwaga! Po zakończeniu działania programów wszystkie obiekty IPC mają zostać usunięte z systemu!
Napisać program umożliwiający grę w kółko i krzyżyk. Program uruchamiany dwukrotnie z różnych konsol (dla dwóch graczy) z dwoma argumentami: kluczem segmentu pamięci współdzielonej i kluczem zestawu semaforów. Pierwszy proces tworzy segment pamięci współdzielonej zawierający planszę do gry, drugi proces podłącza się do istniejącego segmentu. Kolejność ruchów powinna być synchronizowana za pomocą semaforów. Obydwa procesy powinny sygnalizować zakończenie gry (wygrana, przegrana, remis). Zwrócić uwagę na dobór kluczy (istnieje szansa wyboru tych samych kluczy przez różne osoby). Uwaga! Po zakończeniu działania programów wszystkie obiekty IPC mają zostać usunięte z systemu!
wips1