Sitek-wykłady, Komunikacja między procesami, Komunikacja między procesami: sygnały


Komunikacja między procesami: sygnały

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ł.

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:

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> (zobacz man 7 signal).

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):

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).

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.

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.)

Polecenia dotyczące sygnałów:

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

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:

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

  2. 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

  3. jeżeli pid == 0, to sygnał jest wysyłany do wszystkich procesów należących do tej samej grupy, co aktualny proces

  4. 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

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.

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ć.

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().

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.

Blokowanie sygnałów:

Może się zdarzyć, że będziemy chcieli poinformować jądro o tym, że nie chcemy żeby przekazywał bezpośrednio do danego procesu niektóre sygnały. Możemy na przykład mieć w kodzie jakiś krytyczny fragment, którego wykonanie nie powinno zostać przerwane przez sygnały. Robi się to przez ustalenie tzw. maski sygnałów. Maska sygnałów jest zbiorem sygnałów, tzn. pewną strukturą w której każdemu sygnałowi jest przypisany jeden bit (prawda lub fałsz). Struktura taka nosi nazwę sigset_t, i najczęściej jest implementowana w postaci czterobajtowej liczby całkowitej.

Do obsługi struktur sigset_t służą następujące funkcje:

Kiedy już ustawimy zbiór sygnałów powyższymi metodami, możemy użyć funkcji sigprocmask():

int sigprocmask(int how, const sigset_t *set, sigset_t *oset);

Pierwszy parametr wskazuje sposób uaktualnienia maski sygnałów:

Do parametru oset zostanie wpisana zawartość starej maski.

Kiedy jądro próbuje przekazać do procesu sygnał, a ten aktualnie jest zablokowany (nie dotyczy sygnałów SIGKILL i SIGSTOP - tych nie można blokować), to sygnał jest przechowywany do czasu, kiedy proces albo ustawi akcję dla tego typu sygnału na ignorowanie, albo odblokuje dany sygnał (w tym przypadku sygnał jest mu przekazywany w momencie odblokowania).

int sigpending(sigset_t *set);

Za pomocą tej funkcji możemy z wnętrza procesu odczytać listę sygnałów, które oczekują na odblokowanie przez niego. Do zmiennej set jest wpisywany zbiór oczekujących sygnałów, które można sprawdzić funkcją sigismember().

int sigaction(int signo, const struct sigaction *act, struct sigaction *oact);

Struktura sigaction jest zdefiniowana następująco:

struct sigaction

{

void (*sa_handler)();

sigset_t sa_mask;

int sa_flags;

};

Jest to rozszerzona wersja funkcji signal, służąca do tego samego czyli do zmiany dyspozycji sygnału. Zmienna sa_handler zawiera wskaźnik do funkcji obsługi sygnału. sa_mask zawiera zbiór sygnałów, które mają być zablokowane na czas wykonania tej funkcji. W ten sposób możemy się zabezpieczyć przed odebraniem jakiegoś sygnału (i w konsekwencji wykonaniem jego funkcji) w czasie, kiedy jeszcze wykonuje się funkcja obsługująca inny sygnał. W szczególności drugie obsłużenie tego samego sygnału podczas obsługiwania pierwszego jego egzemplarza jest zawsze blokowane.

int sigsuspend(const sigset_t *sigmask);

Funkcja ta działa następująco: podmienia tymczasowo maskę sygnałów procesu na tą wskazaną w sigmask, a następnie wstrzymuje wykonanie programu do czasu otrzymania jakiegoś sygnału. Przydaje się to np. w sytuacji kiedy chcielibyśmy wykonać funkcję pause() aby zaczekać na jakiś sygnał, a jest on w danej chwili zablokowany.



Wyszukiwarka

Podobne podstrony:
wyklad 1 oddzialywania miedzyczasteczkowe 2009
EKONOMIA MIĘDZYNARODOWA 16.11.2014-uzupełnienie, V rok, Wykłady, Ekonomia międzynarodowa
6 wykład komunikacja społeczna, pliki zamawiane, edukacja
Międzynarodowe Stosunki Gospodarcze wykład 1, Szkoła, Międzynarodowe stosunki gospodarcze
wykład 1 prawo międzynarodowe publiczne
Wykład VI - umiędzynarodowienie procesu studiowania, materiauy
EKONOMIA MIĘDZYNARODOWA 26.10.2014, V rok, Wykłady, Ekonomia międzynarodowa
Ekonomia 2 - wykłady, Stosunki międzynarodowe UO
Międzynarodowe rynki finansowe wykłady, Studia, międzynarodowe rynki finansowe
Pytania na Bilskiego, Podręczniki i materiały dydaktyczne, wykłądy, finanse międzynarodowe
socjologia, WYKLAD 2 grupy spoleczne i procesy grupowe
2009-02-26, pedagogium, wykłady, Komunikacja społeczna
pr miedzynar wykład V, prawo międzynarodowe
egz fin mn 2010, Podręczniki i materiały dydaktyczne, wykłądy, finanse międzynarodowe
Wykład 5, Finanse międzynarodowe - dr M. Kąkol
Wykład 7 Komunikat Kod Kanał 3

więcej podobnych podstron