Sygnaly ------- 1. Kompilacja: wywolaj program `make' 2. Uzytkowanie: uruchamianie programow 3. Pliki: err.c, err.h Obsluga bledow. sigproc.c Tworzy wlasna grupe procesow, a potem 10 potomkow. Z tych potomkow pieciu (o nieparzystych numerach) tworzy wlasne grupy. Po pieciu sekundach proces macierzyty wysyla sygnal INT do wszystkich czlonkow swojej grupy. Zabici zostaja Ci, ktorzy nie utworzyli wlasnych grup. Pozostali po 15 sekundach koncza prace. Natychmiast po zakonczeniu programu `sigproc' uruchom program `ps' aby zobaczyc, tych, ktorzy przezyli. sigrace.c Tworzy potomka, ktorego zadaniem jest wysylanie sygnalu INT do procesu macierzystego. Proces macierzysty przechwytuje sygnal INT i wypisuje komunikat, a potem znow ustawia przechwytywanie sygnalu INT. Jesli sygnal INT od potomka przyjdzie przed wywolaniem signal w `lapsygnal', to nieuodporniony na INT proces macierzysty zostanie zabity. Na tym polega wyscig. Normalnie proces powinien zaczac obsluge sygnalu od odpowiedniego wywolania funkcji `signal'. Nacisniecie control-C na terminalu powoduje wyslanie sygnalu INT do wszystkich procesow z tym terminalem zwiazanych. Zauwaz, ze jesli w trakcie wyscigu nacisniesz control-C, to oba procesy go przechwyca. Tylko proces macierzysty wykonal wstepne `signal', natomiast potomny odziedziczyl te obsluge w wyniku wywolania `fork' --- `fork' zachowuje obsluge sygnalow. Procesy przechwytuja takze sygnal QUIT, ktory mozna wywolac naciskajac na klawiaturze control-\. sigwait.c Tworzy 15 procesow, ktore koncza sie z kodem bedacym ich numerem. Nastepnie proces macierzysty czeka trzy sekundy i probuje wykonac `wait' odpowiednia liczbe razy. Program ilustruje to, ze jesli SIGCLD jest ignorowany, to nie tworza sie strzygi (zombies). Wywolaj program bez parametrow, SIGCLD nie bedzie ignorowany i strzygi powstana. Jesli podasz jakis parametr, to strzygi nie powstana i `wait' od razu zwroci -1 z komunikatem o braku potomkow. timeout.c Program wczytuje z terminala znaki. Jesli przez piec sekund nic nie zostanie wpisane, program to wykrywa i wypisuje odpowiedni komunikat. Ilustracja przerywania funkcji `read' przez sygnal. 5. Co mozna zrobic z sygnalem po jego otrzymaniu? (a) Zignorowac ============== main() { signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); /* itd */ } (b) Posprzatac i zakonczyc dzialanie ==================================== int moje_dzieci; void porzadki(int typ_syg) { unlink("/tmp/plik_rob"); kill(moje_dzieci, SIGTERM); wait(0); fprintf(stderr, "program konczy dzialanie ...\n"); exit(1); } main() { signal(SIGINT, porzadki); open("/tmp/plik_rob", O_RDWR | O_CREAT, 0644); moje_dzieci = fork(); /* itd */ } (c) Dokonac dynamicznej rekonfiguracji ====================================== void czytaj_plik_konf (int typ_syg) { int fd; fd = open("moj_plik_konf", O_RDONLY); /* czytanie parametrow konfiguracyjnych */ close(fd); signal(SIGUSR1, czytaj_plik_konf); } main() { czytaj_plik_konf(); /* inicjalna konfiguracja */ while(1) { /* obsluga w petli */ ... } } (d) Przekaz raport nt stanu/dokonaj zrzutu wewnetrznych tablic ============================================================== int licznik; void drukuj_info(int typ_syg) { /* drukuj info o stanie */ printf("liczba skopiowanych blokow: %d\n", licznik); signal(SIGUSR1, drukuj_info); } main () { signal(SIGUSR1, drukuj_info); for (licznik=0; licznik