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)