Zarządzanie sygnałami w systemie Linux
Transkrypt
Zarządzanie sygnałami w systemie Linux
Ćwiczenie 9 Sygnały w systemie Linux 1. Cel ćwiczenia Ćwiczenie wprowadza w zagadnienia związane z wykorzystaniem sygnałów w systemie Linux. Przedstawia najpopularniejsze rodzaje sygnałów i implementuje je w przykładowych programach. 2. Przygotowanie do ćwiczenia • • • • definicja sygnału w systemie Linux (UNIX), przykładowe sygnały, obsługa przechwytywania sygnału, maskowanie sygnałów. 3. Wprowadzenie Sygnał jest odpowiedzią jądra systemu na wyjątkowy stan, jaki wystąpił podczas wykonywania programu przez proces użytkownika. Sygnał przerywa normalne wykonywanie programu i rozpoczyna akcję jego zakończenia (lub wyświetla komunikat o błędzie). Sygnały zdefiniowane w systemie Linux mogą być dostarczane do procesu przez inny proces lub przez jądro systemu. Z każdym sygnałem związana jest akcja podająca sposób jego obsługi. Program użytkownika reaguje na sygnały z wykorzystaniem funkcji signal. Program może: • • • podjąć akcję standardową, zignorować sygnał, podjąć akcję własną. Najczęściej wykorzystywane przez sygnały akcje to utworzenie obrazu pamięci i zakończenie procesu. Akcja własna jest definiowana przez użytkownika w programie obsługi sygnału. Program obsługi sygnału wywoływany jest przez system po odbiorze sygnału przez proces (program obsługi przechwycił lub złapał sygnał). Sygnałami, które nie mogą być zignorowane ani złapane są sygnały SIGSTOP i SIGKILL. 4. Definiowanie akcji Program użytkownika definiuje akcję, która ma być podjęta w przypadku odbioru sygnału za pomocą funkcji systemowej signal (plik signal.h). Zbiór signal.h definiuje różne literały używane jako argumenty przez funkcję systemową signal. Wywołanie funkcji ma postać: signal(sigtype, ptr) Wyższa Szkoła Gospodarki w Bydgoszczy Instytut Informatyki Stosowanej Laboratorium systemów operacyjnych (2010) gdzie sigtype jest liczbą całkowitą albo literałem określającym sygnał, którego akcja ma być zdefiniowana, a ptr – wskaźnikiem funkcji definiującej akcję, albo literałem podającym wcześniej zdefiniowana akcję (SIG_IGN – brak akcji, SIG_DFL – akcja standardowa). nazwa wartość opis SIGHUP 01 linia terminala zawieszona SIGINT 02 przerwanie programu SIGQUIT 03 wyjście z programu SIGILL 04 nielegalna instrukcja SIGTRAP 05 nakaz śledzenia procesu SIGIOT 06 wyst. pułapki przy wyk. operacji I/O SIGEMT 07 wykonana instrukcja emulacji SIGFPE 08 błąd przy operacji zmiennoprzecink. SIGKILL 09 zabicie procesu SIGBUS 10 błąd magistrali SIGSEGV 11 naruszenie segmentacji SIGSYS 12 zły argument funkcji systemowej SIGALRM 14 upłynął czas zegara czasu rzeczyw. SIGTERM 15 programowy sygnał zakończenia akcja standardowa zakończ proces zakończ proces utwórz obraz pamięci utwórz obraz pamięci utwórz obraz pamięci utwórz obraz pamięci utwórz obraz pamięci utwórz obraz pamięci zakończ proces utwórz obraz pamięci utwórz obraz pamięci utwórz obraz pamięci zakończ proces zakończ proces Napisz i skompiluj poniższy program: #include <stdio.h> main() { int i,j; if (fork() == 0) for(i=1; i<=1000; ++i) printf("proces potomny\n"); else for(j=1; j<=1000; ++j) printf("proces macierzysty\n"); } W powyższym przykładzie naciśnięcie klawisza Del przerywa obydwa procesy (procesy nie są chronione). Blokadę sygnału, czyli ochronę programu przed sygnałem uzyskuje się za pomocą wywołania: signal(SIGINT, SIG_IGN) #include<stdio.h> #include<signal.h> main() { int i,j; if (fork() == 0) { signal(SIGINT, SIG_IGN); for(i=1; i<=100; ++i) printf("proces potomny %d\n", i); } else { for(j=1; j<=200; ++j) printf("proces macierzysty %d\n", j); } Wyższa Szkoła Gospodarki w Bydgoszczy Instytut Informatyki Stosowanej Laboratorium systemów operacyjnych (2010) Przerwanie programu klawiszem Del ma wpływ tylko na proces macierzysty. Proces potomny jest wykonywany bez przeszkód do końca. Przywrócenie sygnałowi jego akcji standardowej dokonuje się za pomocą wywołania: signal(sigtype, SIG_DFL) gdzie sigtype jest literałem definiującym sygnał, który chcemy przywrócić. Poniższy przykład pokazuje jak użytkownik może sam, nie zważając na mechanizmy systemowe, zrealizować technikę wzajemnego wykluczania: #include<stdio.h> #include<signal.h> #define BUF 5 main() { FILE *fp; char *record; record = "Test"; signal(SIGINT, SIG_IGN); fp = fopen("new_file", "w"); fwrite(record, 1, BUF, fp); signal(SIGINT, SIG_DFL); fclose(fp); } W powyższym przykładzie sygnał przerwania jest ignorowany w czasie wczytywania z tablicy rekord do pliku. Po wykonaniu programu w pliku new_file pojawi się napis Test. Operacja ta nie jest przerywana. Przechwycenie sygnału i określenie akcji własnej jest wykonywane z wykorzystaniem odpowiedniej funkcji systemowej definiującej tę nową akcję. Funkcja ta występuje jako argument funkcji systemowej signal. Wywołanie funkcji ma postać: signal(sigtype, newptr) gdzie sigtype jest literałem określającym sygnał, który ma być przechwycony, a newptr – wskaźnikiem funkcji definiującej nową akcję. Dzięki niej program wykonuje dodatkowe operacje przed przerwaniem przez sygnał. #include<stdio.h> #include<signal.h> main() { int przechwyc(), i=100; printf(“Nacisnij klawisz przerwania, aby zatrzymac\n”); signal(SIGINT, przechwyc); while (i > 0) { printf(“Program sie wykonuje\n”); i--; } } przechwyc() { printf(„Program sie zakonczyl\n”); exit(1); } Wyższa Szkoła Gospodarki w Bydgoszczy Instytut Informatyki Stosowanej Laboratorium systemów operacyjnych (2010) Przerwanie programu nie kończy natychmiast jego wykonywania jak to jest w przypadku podjęcia akcji standardowej po wystąpieniu sygnału SIGINT, ale prowadzi do podjęcia akcji własnej, polegającej na wyświetleniu napisu i dopiero wtedy proces ulega zakończeniu. 5. Literatura [1] Z. Królikowski, M. Sajkowski: System operacyjny UNIX dla początkujących i zaawansowanych, Wydawnictwo NAKOM, Poznań 1995. Wyższa Szkoła Gospodarki w Bydgoszczy Instytut Informatyki Stosowanej Laboratorium systemów operacyjnych (2010)