so lab.doc

(42 KB) Pobierz
Artur Sosnówka

Założenia:

  • używany dowolny edytor tekstowy (ze wskazaniem na vim)

·         wszystkie programy pisane w ANSI C

·         kompilator gcc

·         debuger gdb

·         do każdego zadania (poza 1) plik makefile

  • studenci muszą wiedzieć co będzie tematem kolejnych zajęć
  • ocenianie programów: program skończony na zajęciach (5), program doniesiony po tygodniu (4), program doniesiony po 2 tygodniach (3), …
  • podstawą zaliczenia jest oddanie przez studenta wszystkich programów
  • na każdych zajęciach studenci piszą krótki (1-2 pytania) test z zakresu zajęć poprzednich

 

  1. Laboratorium 1

 

Wstęp teoretyczny:

  • Podstawowe polecenia basha do niezbędne do pracy na laboratoriach przy pisaniu, kompilacji i uruchamianiu programów (ls, cd, mkdir, mv, man, apropos, …).

·         Użycie i podstawowe przełączniki kompilatora gcc

·         Użycie i podstawowe polecenia debugera gdb

  • Konstrukcja prostego pliku makefile (bez zmiennych) i użycie programu make do budowania programu.

 

Zadanie:

  • Studenci muszą napisać swoją wersję programu id, wyświetlającą identyfikatory rzeczywiste użytkownika i jego grupy głównej oraz związane z nimi nazwy (f-cje: getuid, getgid, getpwuid, getgrgid). Z każdym studentem przećwiczyć na gotowym programiku użycie debugera gdb.

 

  1. Laboratorium 2

 

Wstęp teoretyczny:

  • Konstrukcja pliku makefile ze zmiennymi predefiniowanymi i zmiennymi użytkownika
  • Różnice między biblioteką statyczną i współdzieloną

 

Zadanie:

  • Studenci piszą program na podstawie kodu z poprzednich zajęć. Program zostaje rozdzielony na dwa pliki:
    • plik główny z f-cją main, który sprawdza i wyświetla identyfikatory użytkownika i grupy, a następnie próbuje załadować bibliotekę współdzieloną zawierającą dwie f-cje, które na podstawie podanych identyfikatorów zwrócą nazwy użytkownika i grupy.
    • plik biblioteczny z dwoma funkcjami pobierającymi identyfikatory użytkownika i grupy i zwracające odpowiednie nazwy.

 

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ę.

 

  1. Laboratorium 3

 

Wstęp teoretyczny:

  • Tworzenie procesu (fork), kończenie procesu (exit), synchronizacja procesów (wait, waitpid), pobieranie identyfikatorów procesów (getpid, getppid).
  • Zależności między procesami macierzystymi i potomnymi, różne przypadki zakończenia procesów (np. przedwczesne zakończenie rodzica, zakończenie potomka bez wywołania wait ze strony rodzica).
  • Analiza informacji zwracanych przez wait (identyfikator i status zakończenia), sytuacja błędna w przypadku przyjścia innego sygnału niż SIGCHLD.

Zadanie:

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:

  • procesy nie były wykonywane sekwencyjnie (czyli nie na zasadzie naprzemiennego wywoływania funkcji fork i wait),
  • informacje o zakończeniu się procesów potomnych były odbierane w procesie głównym kolejno według czasu zakończenia się tych procesów,
  • sprawdzać poprawne zakończenie funkcji wait,
  • kontrolować ilość utworzonych i zakończonych procesów potomnych,
  • poprawnie zainicjować generator liczb pseudolosowych w każdym procesie potomnym.

 

  1. Laboratorium 4

 

Wstęp teoretyczny:

  • Podstawowe operacje na plikach (open, close, read, write, lseek). Uchwyt do pliku jako indeks do tablicy deskryptorów otwartych plików. Dziedziczenie tablicy deskryptorów w procesie potomnym.
  • Użycie lseek do ustalenia wielkości pliku.
  • Pozycja w pliku jako zmienna systemowa (widziana przez wszystkie zainteresowane procesy !).

Zadanie:

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!

 

  1. Laboratorium 5

 

Wstęp teoretyczny:

  • Katalog jako plik specjalny zawierający wpisy o zawartych w nim plikach i podkatalogach (struktura dirent).
  • Podstawowe operacje na katalogach (opendir, closedir, readdir, rewinddir).

·         Funkcja ftw

  • Pobieranie informacji o pliku (funkce stat i fstat, struktura stat)

Zadanie:

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".

 

  1. Laboratorium 6

 

Wstęp teoretyczny:

  • Wysyłanie sygnałów (kill).
  • Zmiana domyślnej obsługi sygnału (sigaction) – nie używać signal !!!
  • Wykorzystanie rozszerzonej funkcji obsługi sygnału (pole sa_sigaction struktury sigaction)
  • Blokowanie sygnałów (sigprocmask)
  • Wpływ przychodzących sygnałów na działanie f-cji wait.

Zadanie:

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.

 

  1. Laboratorium 7

 

Wstęp teoretyczny:

  • Wykorzystanie f-cji z rodziny exec do uruchamiania nowego programu w kontekście istniejącego procesu.

Zadanie:

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.

 

  1. Laboratorium 8

 

Wstęp teoretyczny:

  • Komunikacja międzyprocesowa z wykorzystaniem kolejek FIFO (potoków nazwanych)
  • Tworzenie kolejek (mkfifo, mknod), podstawowe operacje (otwieranie, zamykanie, odczyt, zapis)
  • Znaczenie wskaźnik pozycji odczytu i zapisu w potoku
  • Wpływ otwarcia potoku z różnymi flagami (O_RDONLY, O_WRONLY, O_RDWR, O_NONBLOCK) na działanie funkcji open (np. synchronizacja procesu czytającego z piszącym) oraz funkcji odczytu z pustego potoku i zapisu do pełnego potoku.

Zadanie:

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:

 

  1. Klient – wywoływany z jednym argumentem. Argument jest pojedynczą, małą literą alfabetu, która ma zostać zamieniona na wielką literę. Zamiany ma dokonać serwer. Klient tworzy swój własny potok, nadając mu nazwę opartą na swoim identyfikatorze pid, następnie otwiera do zapisu potok serwera, zapisuje do tego potoku literę podaną jako argument oraz swój pid. W kolejnym kroku klient otwiera do odczytu utworzony wcześniej prywatny potok i próbuje z niego odczytać odpowiedź serwera (wielką literę). Po otrzymaniu odpowiedzi wyświetla ją, zamyka i kasuje swój potok, zamyka potok serwera i kończy działanie.
  2. Serwer – wywoływany bez argumentów. Po uruchomieniu tworzy swój potok (nazwa potoku będzie ogólnie znana klientom), otwiera go i czeka na pojawienie się w nim informacji od klientów. Po odczytaniu informacji od klienta zamienia otrzymaną literą, otwiera potok kliencki do zapisu (wraz z literą dostał pid klienta, więc jest w stanie ustalić nazwę jego prywatnego potoku) i zapisuje do niego odpowiedź (wielką literę). Następnie zamyka potok kliencki i ponownie próbuje odczytać dane ze swojego potoku (czeka na kolejnego klienta).

 

  1. Laboratorium 9

 

Wstęp teoretyczny:

  • Programowanie wątków z wykorzystaniem bibliotek pthread. Tworzenie wątków, synchronizacja, blokowanie dostępu do sekcji krytycznej (muteksy).

Zadanie:

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).

 

  1. Laboratorium 10

 

Wstęp teoretyczny:

  • Komunikacja międzyprocesowa z wykorzystaniem kolejek komunikatów (biblioteka IPC, funkcje msgget, msgctl, msgsnd, msgrcv, polecenia ipcs, ipcrm).
  • Wpływ wartości typu komunikatu (mtype) na funkcjonowanie obiektu kolejki komunikatów.

Zadanie:

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!

 

  1. Laboratorium 11

 

Wstęp teoretyczny:

  • Komunikacja międzyprocesowa z wykorzystaniem pamięci współdzielonej (biblioteka IPC, funkcje shmget, shmctl, shmat, shmdt)
  • Synchronizacja za pomocą semaforów (biblioteka IPC, funkcje semget, semctl, semop).

Zadanie:

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!

 

Zgłoś jeśli naruszono regulamin