Instrukcja

by Paweł Paduch published 2018/12/14 13:23:00 GMT+2, last modified 2023-10-12T12:16:50+02:00
Poznajemy funkcje fork, wait i signal

 

Tworzenie i kończenie procesów

To laboratorium ma na celu zapoznanie się z funkcją fork, wait oraz na sposobie przechwytywania sygnałów (funkcja signal)

  1. Wstęp
    Jedynym sposobem na stworzenie nowego procesu w systemie Unix jest wywołanie funkcji systemowej fork(). (man fork) inne funkcje np. clone vfork są interfejsami do fork'a. Funkcją związaną ściśle z forkiem jest wait  czekanie na zakończenie potomstwa.
    Sygnały. Do przechwycenia sygnału służy funkcja signal. Do wysyłania sygnałów służy funkcja kill.

  2. Napisać/przepisać i uruchomić poniższy program, zrozumieć jak działa.
    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
    int main() { int childpid; int status=1; int zakonczono; printf("startuje proces macierzysty pid %d\n",getpid()); if ((childpid = fork()) == -1) { perror("nie moge forknac"); exit(1); } else if (childpid ==0 ) { printf("Proces potomny o pidzie %d z rodzica %d\n",getpid(),getppid()); } else { printf("Proces macierzysty o pidzie %d i dziecku %d\n",getpid(),childpid); } exit(0); }
  3. Sprawić by proces potomny zakończył się po procesie macierzystym [0,5pkt] (funkcja sleep).
    Sprawdzić identyfikator procesu macierzystego w procesie potomnym po zakończeniu rodzica. Sprawić by proces potomny zakończył się przed końcem rodzica (rodzic jeszcze nie wywołuje wait). Zbadać czy proces potomny widnieje jeszcze w systemie (ps -efa).

  4. Zastosować funkcję wait [0,5pkt]
    odbierając wynik zakończenia procesu potomnego. Sprawdzić zachowanie się obu procesów. Proces potomny powinien zwrócić wartość inną niż 0 np. exit(2). Wyświetlić co odbierze wait w sposób niesformatowany (nie używać  WEXITSTATUS czy przesunięć bitowych).

  5. Stworzyć n=5 procesów potomnych z jednego procesu macierzystego.  [1,5pkt]
    Zastosować funkcję wait do poprawnego zakończenia. Każdy potomek powinien zatrzymać się na 5 sekund (sleep) by na drugiej konsoli sprawdzić za pomocą ps -efa czy udało się wygenerować dokładnie 5 potomków (ps powinien pokazać 5 procesów potomnych i 1 macierzysty). Nie powinniśmy mieć procesów osieroconych ani "zombie" (<defunct>). Procesy powinny zaczynać się razem i kończyć razem, czyli jednocześnie, to znaczy bez opóźnień.  Zastosować pętlę zamiast konstrukcji if else if else ...

  6. Stworzyć n=5 pokoleń [1,5pkt]
    rodzic->potomek1->potomek2->...->potmek5. Uwaga występuje ryzyko zapętlenia tworzenia procesów. Zadbać o to by nie stracić kontroli nad systemem. Zapisać też edytowane pliki. Sprawdzić jak powyżej, czy udało się wygenerować dokładnie 5 potomków (ps powinien pokazać 5 procesów potomnych + 1 macierzysty). Nie powinniśmy mieć procesów osieroconych ani "zombie" (<defunct>). Procesy powinny zaczynać się razem i kończyć razem, czyli jednocześnie, to znaczy bez opóźnień. Zastosować pętlę zamiast konstrukcji if else if else ...

  7. Przykład [1pkt]
    przechwycenia sygnału SIGCHLD - wysyłanego przez dziecko w momencie zakończenia się. Zastosować poniższy przykład w dowolnym z wykonanych programów.
    #include  <signal.h> /* w tym pliku jest definicja sygnalow */
    /* przykładowa funkcja obsługi sygnału */
    void oblsluga_zakonczenia_dziecka(int nr_sig)
    {
    printf("Rodzic już się dowiedział o zakończeniu procesu %d\n",wait(NULL));
    }
    /* poinformowanie procesu by w razie nadejścia sygnału SIGCHLD wywołał funkcję obsluga_zakonczenia_dziecka */
    signal(SIGCHLD,oblsluga_zakonczenia_dziecka);
  8. Sprawozdanie

        Nie zapomnijcie o sprawozdaniu