Instrukcja
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)
- 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. - 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); } - 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). - 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). - 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 ... - 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 ... - 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);
- Sprawozdanie
Nie zapomnijcie o sprawozdaniu