background image

Obsługa sygnałów zgodna ze 
standardem Posix

background image

Wprowadzenie

Sygnały są formą komunikacji między procesami w systemie 
Unix.

  Sygnał  jest  to  pewien  komunikat  wysyłany  do  procesu, 
oznaczający że proces ma chwilowo przerwać wykonywanie. 

Pojawia się on asynchronicznie, tzn. w dowolnym momencie 
w czasie pracy procesu, niezależnie od tego co dany proces 
akurat robi. 

Proces nie wie z góry że otrzyma sygnał. 

background image

Wprowadzenie

Otrzymanie  sygnału  zazwyczaj  znaczy,  że  nastąpiło  jakieś 
zdarzenie 

wyjątkowe, 

które 

wymaga 

od 

procesu 

natychmiastowej reakcji.

  Sygnały  są  zazwyczaj  używane  do  takich  zadań  jak  kończenie 
działania  procesów,  czy  informowanie  demonów,  że  mają 
ponownie odczytać pliki konfiguracyjne.

Proces może otrzymać sygnał od: 

jądra - np. w wyniku zdarzenia związanego ze sprzętem 

innego procesu - za pomocą funkcji opisanych dalej 

użytkownika - użycie polecenia kill, albo naciśnięcie kombinacji 
klawiszy (np.ctrl-c) 

background image

Wprowadzenie

W  zależności  od  rodzaju  zdarzenia  i  żądanej  reakcji, 

wysyłane może być wiele różnych typów sygnałów. 

Każdy sygnał ma przypisany numer oraz nazwę zaczynającą 

się od "SIG". Nazwy te są zdefiniowane w pliku <signal.h> 

W momencie otrzymania sygnału proces wstrzymuje 

aktualnie wykonywaną pracę, i reaguje na sygnał na jeden z 

trzech sposobów (tzw. akcja lub dyspozycja dla sygnału): 

przechwycenie sygnału, tzn. wykonanie zdefiniowanej w 

programie akcji 

zignorowanie sygnału 

wykonanie akcji domyślnej, skojarzonej z danym typem sygnału 

- najczęściej zakończenie procesu w pewien sposób 

background image

Wprowadzenie

Po  obsłużeniu  sygnału  przerwany  proces  kontynuuje 

działanie  od  miejsca  przerwania  (o  ile  nie  został 

zakończony). 

Dwa  sygnały  -  SIGKILL  i  SIGSTOP  -  nie  mogą  zostać 

przechwycone  ani  zignorowane.  Po  otrzymaniu  któregoś  z 

nich  proces  musi  wykonać  akcję  domyślną.  Daje  nam  to 

możliwość 

bezwarunkowego 

zatrzymania/zakończenia 

dowolnego procesu, jeżeli zajdzie taka potrzeba. 

Nie  powinno  się  ignorować  również  niektórych  sygnałów 

związanych  z  błędami  sprzętowymi  (np.  dzielenie  przez  0, 

czy niepoprawne odwołanie do pamięci).

background image

Wprowadzenie

Jeśli  chcemy  przechwytywać  jakiś  sygnał,  musimy 

zdefiniować  funkcję  która  będzie  wykonywana  po 

otrzymaniu  takiego  sygnału,  oraz  powiadomić  jądro  za 

pomocą funkcji signal(), która to funkcja.

Dzięki  temu  możemy  np.  sprawić  że  po  naciśnięciu  przez 

użytkownika  ctrl+c,  nasz  program  zdąży  jeszcze  zamknąć 

połączenia sieciowe czy pliki, usunąć pliki tymczasowe itd.

background image

Rodzaje sygnałów

Są to wybrane sygnały, lista wszystkich sygnałów jest nieco 
dłuższa. Zestawy sygnałów, numery im przypisane i sposób 
ich  obsługi  mogą  się  nieco  różnić  w  różnych  wersjach 
Unixów.

SIGHUP (1) - zerwanie łączności z terminalem; jest wysyłany wtedy, gdy 
użytkownik  rozłączy  się  z  terminalem  z  którym  związany  jest  dany 
proces  (np.  przez  wylogowanie);  służy  do  zakończenia  wszystkich 
programów  w  momencie  zakończenia  sesji  na  terminalu;  inny  sposób 
wykorzystania  tego  sygnału  to  powiadomienie  procesów  demonów,  że 
powinny  przeładować  pliki  konfiguracyjne  (wybrano  ten  sygnał, 
ponieważ  rozłączenie  z  terminalem  nie  jest  istotne  dla  demonów)
[standardowa akcja: zakończenie procesu] 

background image

Rodzaje sygnałów

SIGINT (2) - sygnał przerwania, generowany w momencie naciśnięcia 
przez użytkownika specjalnej kombinacji klawiszy (zwykle ctrl+c lub 
delete); służy np. do przerwania pracy procesu który wyprowadza na 
ekran dużą ilość niepotrzebnych danych 
[standardowa akcja: zakończenie procesu] 

SIGQUIT (3) - generowany po naciśnięciu klawisza zakończenia, 
najczęściej ctrl+\.
[standardowa akcja: zakończenie procesu i zrzut core]

(zrzut core oznacza że w bieżącym katalogu jest tworzony plik "core", a 
w nim zapisywany jest obraz pamięci procesu. Plik ten może być 
wykorzystany np. przez debuggery) 

background image

Rodzaje sygnałów

SIGILL (4) - proces wykonał nieprawidłową instrukcję sprzętową

[standardowa akcja: zakończenie procesu i zrzut core] 

SIGTRAP (5), SIGIOT (6), SIGEMT (7) - błąd sprzętowy, zależny od 

implementacji systemu

[standardowa akcja: zakończenie procesu i zrzut core] 

SIGFPE (8) - wyjątek zmiennopozycyjny (np. dzielenie przez zero lub 

inny błąd operacji arytmetycznej)

[standardowa akcja: zakończenie procesu i zrzut core] 

SIGKILL (9) - sygnał bezwarunkowego zakończenia procesu, którego nie 

da się przechwycić ani zignorować

[standardowa akcja: zakończenie procesu] 

SIGBUS (10) - błąd magistrali (błąd sprzętowy)

[standardowa akcja: zakończenie procesu i zrzut core] 

background image

Rodzaje sygnałów

SIGSEGV (11) - odwołanie do nieprawidłowego adresu w pamięci 

(segmentation violation czyli naruszenie zasad segmentacji)

[standardowa akcja: zakończenie procesu i zrzut core] 

SIGSYS (12) - próba wykonania nieprawidłowej funkcji systemowej 

(nieprawidłowe argumenty)

[standardowa akcja: zakończenie procesu i zrzut core] 

SIGPIPE (13) - próba zapisu do łącza komunikacyjnego, kiedy proces 

czytający z tego łącza zakończył już pracę (dotyczy także komunikacji 

przez gniazda sieciowe)

[standardowa akcja: zakończenie procesu] 

SIGALRM (14) - alarm (pobudka); wysyłany po upłynięciu 

odpowiedniego okresu czasu, ustalonego przez funkcję alarm() ub 

setitimer()

[standardowa akcja: zakończenie procesu] 

background image

Rodzaje sygnałów

SIGTERM (15) - sygnał zakończenia procesu; podobny do SIGKILL, ale 

można go przechwycić albo zignorować; jest to domyślny sygnał 

polecenia "kill"

[standardowa akcja: zakończenie procesu] 

SIGUSR1 (16), SIGUSR2 (17) - sygnały zdefiniowane przez użytkownika

[standardowa akcja: zakończenie procesu] 

SIGCLD / SIGCHLD (18) - zmiana stanu (zakończenie lub zatrzymanie) 

procesu potomnego

[standardowa akcja: zignorowanie sygnału] 

SIGPWR / SIGINFO (19) - niedobór mocy; sygnał jest wysyłany kiedy 

komputer pracuje na zasilaniu awaryjnym (UPS lub bateria), którego 

napięcie spadło do krytycznego poziomu i komputer musi zostać 

zamknięty w ciągu kilkudziesięciu sekund 

[standardowa akcja: zakończenie procesu] 

background image

Rodzaje sygnałów

SIGSTOP - nakaz wstrzymania pracy procesu; nie może zostać 

przechwycony ani zignorowany

[standardowa akcja: zatrzymanie procesu] 

SIGCONT - nakaz kontunuacji pracy, wysyłany po wstrzymaniu 

przez SIGSTOP

[standardowa akcja: kontynuacja lub zignorowanie sygnału] 

SIGTSTP - sygnał zatrzymania; podobny do SIGSTOP, ale może 

zostać zignorowany lub przechwycony; można go wysłać z 

terminalu przez naciśnięcie kombinacji ctrl+z 

[standardowa akcja: zatrzymanie procesu] 

SIGABRT - awaryjne zakończenie (wysyłany za pomocą funkcji 

abort())

[standardowa akcja: zakończenie procesu] 

background image

Polecenia dotyczące sygnałów

 

Z poziomu powłoki do obsługi sygnałów służą polecenia: 

trap (wbudowane polecenie shella) - służy do określania reakcji 

shella na odebranie przez niego poszczególnych sygnałów 

kill - wysłanie do procesu lub grupy procesów określonego 

sygnału; polecenie to jest interfejsem do opisanej niżej funkcji 

systemowej kill(); można podać numer sygnału lub jego nazwę; 

sposób interpretacji podanego PID'a przez polecenie jest 

analogiczne jak w funkcji kill() 

background image

Funkcje ANSI C 
i systemowe dotyczące sygnałów

int kill(pid_t pid, int signo);

Funkcja służy do wysyłania sygnałów do innych procesów. Signo 

to numer sygnału, a pid może zostać podany na kilka sposobów:

 

jeżeli pid > 0, to sygnał jest wysyłany do jednego procesu o 

podanym identyfikatorze pid 

jeżeli pid < 0, to jest wysyłany do grupy procesów o identyfikatorze 

pgid=-pid. czyli podanie pid -48 spowoduje wysłanie sygnału do 

wszystkich procesów należących do grupy 48 

jeżeli pid == 0, to sygnał jest wysyłany do wszystkich procesów 

należących do tej samej grupy, co aktualny proces

akcja dla pid == -1 jest różna na różnych systemach, może to być 

np. wysłanie sygnału do wszystkich procesów należących do tego 

samego użytkownika co proces wysyłający

 

background image

Funkcje ANSI C 
i systemowe dotyczące sygnałów

Wysłanie  sygnału  następuje  tylko  pod  warunkiem, 
że  dany  proces  ma  uprawnienia  do  wysyłania 
sygnałów  podanym  innym  procesom,  oraz  że 
procesy  docelowe  nie  należą  do  grupy  procesów 
systemowych (najczęściej: proces wymiany (0), init 
(1) i demon stronicowania (2)). Jeżeli w polu signo 
podamy  0  (tzw.  sygnał  pusty),  to  funkcja  kill  nie 
wysyła  żadnego  sygnału,  a  tylko  sprawdza  czy 
docelowy proces istnieje.

background image

Funkcje ANSI C 
i systemowe dotyczące sygnałów

int raise(int signo);

Służy do wysyłania sygnałów przez proces do siebie samego.

void (*signal (int signo, void (*func)(int)))(int);

Funkcja ta służy do ustalenia przechwytywania podanego 

sygnału signo. W momencie otrzymania przez proces takiego 

sygnału, o ile jest on przechwytywalny, zostanie wykonana 

funkcja, do której wskaźnik przekazujemy jako parametr func. 

Możemy w to miejsce wstawić także stałą SIG_IGN (sygnał 

będzie wtedy ignorowany) lub SIG_DFL (zostanie wykonana akcja 

domyślna). Funkcja przechwytująca sygnał musi przyjmować 

jeden parametr typu int (numer sygnału) i nic nie zwracać.

background image

Funkcje ANSI C 
i systemowe dotyczące sygnałów

unsigned int alarm(unsigned int seconds);

Służy do ustawienia licznika czasu na podaną liczbę 
sekund. Po upłynięciu zadanego czasu, jądro wyśle do 
procesu sygnał SIGALRM. Może on zostać przechwycony, 
w przeciwnym wypadku zostanie wykonana akcja 
domyślna czyli zakończenie. Jeżeli seconds==0, to 
poprzednio ustawiony licznik jest wyłączany.

int pause(void);

Wykonywanie procesu jest wstrzymywane, do czasu otrzymania 
jakiegokolwiek sygnału (np. SIGALRM ustawionego wcześniej 
funkcją alarm()). Może to być wykorzystane np. do wstrzymania 
procesu na określony czas, jak w funkcji sleep().

background image

Funkcje ANSI C 
i systemowe dotyczące sygnałów

void abort(void);

Wywołanie tej funkcji powoduje awaryjne zakończenie procesu. 
Jest to realizowane przez wysłanie do procesu sygnału SIGABRT, 
którego nie może on zignorować. Może go przechwycić, ale tylko 
w celu wykonania tzw. czynności porządkujących, później 
program i tak zostanie zakończony.


Document Outline