Obsługa sygnałów. Tomasz Borzyszkowski



Podobne dokumenty
Sygnały. 7. Sygnały (2005/2006)

Instrukcja do laboratorium Systemów Operacyjnych. (semestr drugi)

Komunikacja za pomocą potoków. Tomasz Borzyszkowski

Programowanie Współbieżne. W Linuxie/Unixie

Systemy Operacyjne 1 Laboratorium 2 Procesy i sygnały w Linuksie (jeden tydzień) dr inż. Arkadiusz Chrobot

Poniższe funkcje opisane są w 2 i 3 części pomocy systemowej.

przerwany proces móg l zareagować na określone zdarzenie. Można je traktować jako software owe wersje przerwań sprz etowych.

Wykład 5 Przerwania i wywołania systemowe. Wojciech Kwedlo, Systemy Operacyjne II -1- Wydział Informatyki PB

Procesy, pliki, potoki, sygnały - uzupełnienie

Sygnał mechanizm asynchronicznego powiadamiania procesów o zdarzeniach zwykle awaryjnych.

Pliki. Funkcje tworzące pliki i operujące na nich opisane są w części 2 pomocy systemowej. Tworzenie i otwieranie plików:

UNIX. mgr inż. Marcin Borkowski

POSIX: IEEE Std (Issue 6, 2004 edition)

Systemy Operacyjne I: Procesy

Instrukcja do laboratorium Systemów Operacyjnych (semestr drugi)

Linux: Procesy. Systemy Operacyjne. Mateusz Hołenko. 26 marca 2013

Sygnały i ich obsługa

Laboratorium Procesy w systemach UNIX 3.2 Polecenia związane z procesami

4. Procesy pojęcia podstawowe

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

Model procesu w systemie Linux. Tomasz Borzyszkowski

procesy odrębne dzielone

SYSTEMY OPERACYJNE I laboratorium 3 (Informatyka stacjonarne 2 rok, semestr zimowy)

Projektowanie oprogramowania systemów PROCESY I ZARZĄDZANIE PROCESAMI

Mechanizmy z grupy IPC

Wykład 5: Klasy cz. 3

4. Procesy pojęcia podstawowe

Instrukcja do laboratorium Systemów Operacyjnych. (semestr drugi)

Programowanie w języku C++

Podstawy Informatyki Układ przerwań

Informatyka I. Klasy i obiekty. Podstawy programowania obiektowego. dr inż. Andrzej Czerepicki. Politechnika Warszawska Wydział Transportu 2018

Wykład 8: klasy cz. 4

Krótki kurs programowania współbieżnego

Łącza nienazwane(potoki) Łącza nienazwane mogą być używane tylko pomiędzy procesami ze sobą powiązanymi.

Zarządzanie procesami

Futex (Fast Userspace Mutex) Łukasz Białek

4. Procesy pojęcia podstawowe

Mechanizmy pracy równoległej. Jarosław Kuchta

Kolejki FIFO (łącza nazwane)

Języki programowania C i C++ Wykład: Typy zmiennych c.d. Operatory Funkcje. dr Artur Bartoszewski - Języki C i C++, sem.

Autor: dr inż. Zofia Kruczkiewicz, Programowanie aplikacji internetowych 1

Instrukcja obsługi. Kamera szybkoobrotowa IP LUMENA-12M1-147

Wątki, sygnały i szeregowanie w systemach UNIX, Linux

Metody obsługi zdarzeń

Przerwania, polling, timery - wykład 9

Podstawy programowania komputerów

1 Obsługiwane funkcje wyzwalaczy

SYSTEMY CZASU RZECZYWISTEGO - VxWorks

Przesyłania danych przez protokół TCP/IP

w odróżnieniu od procesów współdzielą przestrzeń adresową mogą komunikować się za pomocą zmiennych globalnych

Zwielokrotnianie wejścia wyjścia

Pracownia internetowa w każdej szkole (edycja Jesień 2007)

Widoczność zmiennych Czy wartości każdej zmiennej można zmieniać w dowolnym miejscu kodu? Czy można zadeklarować dwie zmienne o takich samych nazwach?

Procesy, wątki i zasoby

Mikroprocesor Operacje wejścia / wyjścia

5. Model komunikujących się procesów, komunikaty

Wyjątki (exceptions)

Działanie systemu operacyjnego

Wykład 3. Procesy i wątki. Wojciech Kwedlo, Wykład z Systemów Operacyjnych -1- Wydział Informatyki PB

Budowa Mikrokomputera

Prezentacja systemu RTLinux

TEMAT : KLASY DZIEDZICZENIE

Ustawienia ogólne. Ustawienia okólne są dostępne w panelu głównym programu System Sensor, po kliknięciu ikony

Podstawy programowania w języku C++

Delphi Laboratorium 3

Współbieżność w środowisku Java

Działanie systemu operacyjnego

Skrypty startowe. Tryb interaktywny tryb logowania: nie logowanie: Tryb nieinteraktywny

Systemy operacyjne III

Wykład 4 Delegat (delegate), właściwości indeksowane, zdarzenie (event) Zofia Kruczkiewicz

Sesje, ciasteczka, wyjątki. Ciasteczka w PHP. Zastosowanie cookies. Sprawdzanie obecności ciasteczka

UWAGA!!! Przed przystąpieniem do zamknięcia roku proszę zrobić kopie bezpieczeństwa

Modułowy programowalny przekaźnik czasowy firmy Aniro.

kiedy znowu uzyska sterowanie, to podejmuje obliczenie od miejsca, w którym poprzednio przerwała, i z dotychczasowymi wartościami zmiennych,

Podstawy programowania. Wykład: 7. Funkcje Przekazywanie argumentów do funkcji. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD

referencje Wykład 2. Programowanie (język C++) Referencje (1) int Num = 50; zdefiniowano zmienną Num (typu int) nadając jej wartość początkową 50.

Programowanie współbieżne Wykład 2. Iwona Kochańska

Temat zajęć: Obsługa procesów w systemie.

Działanie systemu operacyjnego

Spis treści. 1 Moduł RFID (APA) 3

Tablice (jedno i wielowymiarowe), łańcuchy znaków

Wątki w Android OS. Matt Rutkowski. GynSoft sp. z o.o. matt@gynsoft.net

Działanie systemu operacyjnego

1.1 Definicja procesu

MIERNIK T-SCALE BWS 1

Sieci Komputerowe 2 / Ćwiczenia 2

Część XVII C++ Funkcje. Funkcja bezargumentowa Najprostszym przypadkiem funkcji jest jej wersja bezargumentowa. Spójrzmy na przykład.

PODRĘCZNIK UŻYTKOWNIKA programu Pilot

Wstęp do programowania

IIIIIIIIIIIIIIIMMIMMIII

Rozdział 5. Administracja kontami użytkowników

Architektura komputerów

SYSTEMY OPERACYJNE: STRUKTURY I FUNKCJE (opracowano na podstawie skryptu PP: Królikowski Z., Sajkowski M. 1992: Użytkowanie systemu operacyjnego UNIX)

Zarządzanie procesami (omawiane zagadnienia)

Zaawansowane programowanie obiektowe - wykład 5

System operacyjny MACH

Konfiguracja parametrów pozycjonowania GPS /5

java.util.* :Kolekcje Tomasz Borzyszkowski

Programowanie obiektowe

Lab 9 Podstawy Programowania

Transkrypt:

Obsługa sygnałów Tomasz Borzyszkowski

Wprowadzenie Zaawansowane systemy operacyjne często realizując duże zadania, wykorzystują do ich realizacji wiele współdziałających ze sobą programów/procesów. Do dobrego współdziałania procesy te muszą komunikować się ze sobą. W systemach Unixowych istnieje wiele mechanizmów komunikacji międzyprocesowej. Najczęściej używane to: sygnały, potoki i kolejki FIFO. Na bieżącym wykładzie przyjrzymy się bliżej sygnałom. Sygnały dostarczają prostej metody przekazywania przerwań programowych do procesu Unixowego. Z powodu swojej natury, sygnały są używane raczej do obsługi nietypowych sytuacji, a nie do prostego przesyłania danych pomiędzy procesami. Proces może zrobić z sygnałem następujące rzeczy: Wybrać sposób reakcji po otrzymaniu sygnału (obsługa sygnału) Blokować sygnał, tj. pozostawić go na później; dotyczy krytycznych fragmentów kodu Wysłać sygnał do innego procesu 2

Nazwy sygnałów Sygnały nie mogą bezpośrednio przenosić informacji, co ogranicza ich użyteczność jako ogólnego mechanizmu komunikacji między procesami. Jadnak każdy typ sygnału posiada nadaną mnemoniczną nazwę, wskazującą cel w jakim sygnał jest zwykle używany. Nazwy sygnałów są zdefiniowane w pliku nagłówkowym <signal.h>. Większość sygnałów Unixowych jest przeznaczona do użycia przez jądro, chociaż istnieje również kilka do przesyłania między zwykłymi procesami. Oto kilka wybranych, najczęściej używanych sygnałów: SIGABRT sygnał przerwania procesu wysyłany przez bieżący proces za pomocą funkcji abort. Obsługa tego syganłu powinna się zakończyć tzw. zakończeniem anormalnym. W rzeczywistości następuje zrzut rdzenia (core dump) do pliku w celu dalszej analizy. SIGALRM tzw. zegar alarmu. Wysyłany do procesu przez jądro, gdy upłynie ustalony czas. Wszystkie procesy mają w sumie do dyspozycji trzy czasomierze.czasomierz jest ustawiany przez proces za pomocą funkcji alarm. 3

Nazwy sygnałów cd SIGCHLD proces potomny zakończony lub zatrzymany. Zawsze, gdy proces potomny kończy się lub zatrzymuje, jądro zawiadamia o tym jego proces rodzicielski, wysyłając mu ten sygnał. Domyślnie proces rodzicielski ignoruje sygnał, więc jeżeli chce wiedzieć o każdym ukończonym procesie, musi jawnie przechwytywać sygnał. SIGCONT kontynuuj proces, jeżeli był zatrzymany. Jest to sygnał sterowania pracą, który powinien wznowić proces, jeżeli został zatrzymany. W przeciwnym przypadku proces powiniem ignorować sygnał. Stanowi on przeciwieństwo sygnału SIGSTOP. SIGFPE wyjątek zmiennoprzecinkowy. Wysyłany przez jądro, gdy wystapi błąd obliczeń zmiennoprzecinkowych, np. nadmiar lub niedomiar. Powoduje anormalne zakończenie. SIGINT przerwanie. Wysyłany przez jądro do wszystkich procesów powiązanych z sesją terminala, gdy użytkownik wciśnie klawisz przerwania (Ctrl-c). Jest to powszechnie stosowany sposób zatrzymania działającego programu. 4

Nazwy sygnałów cd II SIGHUP sygnał zawieszenia. Wysyłany przez jądro do wszystkich procesów powiązanych z terminalem sterujacym, jeśli zostaje on odłączony. Wysłany także do wszystkich członków sesji, gdy kończy się proces wiodący sesji, którym zwykle jest proces powłoki, pod warunkiem, że sesja jest powiązana z terminalem sterującym. Dzięki temu, po wylogowaniu użytkownika, jego procesy dziłające w tle są kończone (o ile nie wyłączono obsługi tego sygnału). SIGILL nielegalna instrukcja. Wysyłany przez system, gdy proces próbuje wykonać nielegalna instrukcję. Staje się to możliwe, gdy program uszkodzi swój własny kod lub próbuje wykonać instrukcję zmiennoprzecinkową bez odpowiedniego wsparcia sprzętowego. Sygnał powoduje anormalne zakończenie procesu. 5

Nazwy sygnałów cd III SIGKILL usunięcie. Specjalny sygnał wysyłany do jednego procesu przez inny, aby usunąć odbiorcę. Jest on także czasem wysyłany przez system, np. podczas zamykania systemu. Jest to jeden z dwóch sygnałów, które nie mogą być zignorowane lub przechwycone, tj. obsłużone przez procedurę zdefinowaną przez użytkownika. SIGSTOP zatrzymanie wykonania. Jest to sygnał kontroli zdarzeń, który zatrzymuje proces. Podobnie jak SIGKILL, nie może zostać przechwycony lub zignorowany. SIGTERM programowy sygnał zakończenia. Zwyczajowo jest używany do kończenia procesu. Programista może użyć tego sygnału, aby dać procesowi trochę czasu na działania porządkujące przed wysłaniem sygnału SIGKILL. SIGUSR1 i SIGUSR2 podobnie jak SIGTERM, sygnały te nigdy nie są wysyłane przez jądro. Mogą być wykorzystane przez użytkownika w dowolnym celu. 6

Obsługa sygnałów Po otrzymaniu sygnału proces ma do wyboru jeden z trzech sposobów działania: Podejmij działania domyślne, stosowne do otrzymanego sygnału Zignoruj sygnał całkowicie i kontynuuj przetwarzanie Podejmij działania zdefiniowane przez użytkownika W starszych wersjach Unixa obsługa sygnałów była względnie prosta, choć czasem zawodziła. Nowe procedury, które przedstawimy, są bardziej niezawodne i jednocześnie bardziej złożone. Jednym z głównych parametrów przekazywanych do funkcji systemowych obsługujących sygnały są tzw. zestawy sygnałów. Określają one listy sygnałów, z którymi chcemy coś zrobić. Zestawy sygnałów są definiowane za pomocą typu sigset_t, zdefiniowanego w pliku nagłówkowym <signal.h>. Typ ten jest wystarczająco pojemny, aby zapamiętać reprezentację wszystkich zdefiniowanych w systemie sygnałów. 7

Zestawy sygnałów implementacja Użytkownik może definiować zestawy potrzebnych mu sygnałów za pomocą następujących funkcji: int sigemptyset(sigset_t *set); int sigfillset (sigset_t *set); Pierwsza z funkcji inicjuje zestaw funkcji, wskazywany przez set tak, że wszystkie sygnały są wyłączone, natomiast druga inicjuje zestaw funkcji, wskazywany przez set tak, że wszystkie sygnały są włączone. Kolejne funkcje to: int sigaddset(sigset_t *set, int signo); int sigdelset(sigset_t *set, int signo); Funkcje te, odpowiednio, dodają do i usuwają z zestawu sygnałów wskazywajego przez set, sygnał signo. Zalecane jest by parametr signo był nazwą sygnału, taką jak np. SIGINT. Podanie rzeczywistego numeru sygnału jest możliwe ale niezalecane ze względu na przenośność kodu. 8

Ustalanie działania sygnału Po zdefiniowaniu zestawu sygnałów można wybrać konkretną metodę obsługi sygnałów używając funkcji: int sigaction(int signo, const struct sigaction *act, const struct sigaction *oact); Parametr signo identyfikuje sygnał, dla którego chcemy określić działanie. Może to być dowolny sygnał, z wyjątkiem SIGSTOP i SIGKILL. Drugi parametr określa działanie, jakie chcemy ustawić dla signo. Trzeci parametr jest ustawiany na NULL lub na aktualne ustawienia. Struktura sigaction składa się z następujących pól: void (* sa_handler)(int) identyfikuje działanie, jakie ma być podjęte po otrzymaniu sygnału. Może przyjmować jedną z następujących wartości: SIG_DFL domyślne działanie systemu, SIG_IGN zignoruj ten sygnał (nie dla SIGSTOP i SIGKILL) albo adres funkcji wywoływanej po otrzymaniu sygnału. Sygnał zostanie przekazany do funkcji jako jej argument. 9

Struktura sigaction sigset_t sa_mask maska sygnałów, które powinny być blokowane podczas wywoływania funkcji sa_handler. Dodatkowo, sygnał, który wywołał funkcję będzie zablokowany (dodany do sa_mask), chyba że użyto flagę SA_NODEFER lub SA_NOMASK. Blokowanie przekształca sygnały w bardziej, ale nie całkowicie, godny zaufania mechanizm komunikacji. int sa_flags zbiór flag, które modyfikują zachowanie procesu obsługi sygnałów. Jest to zbiór wartości połączonych bitowym OR. Zobacz man sigaction. Struktura sigaction posiada również wskaźnik do dodatkowej funkcji obsługi. Standard POSIX nie przewiduje jeszcze jego wykorzystania. Powyższy opis przedstawia tylko wybrane definicje zachowań jakie może podjąć program po otrzymaniu sygnału (patrz dokumnetacja systemowa). Poniższe programy ilustrują typowe wykorzystanie przechwytywania sygnałów. Zobacz: sygnaly1.c sygnaly2.c sygnaly3.c 10

Sygnały a funkcje systemowe W większości przypadków, jeżeli do procesu wysyłany jest sygnał w chwili, gdy wykonuje on funkcję systemową, sygnał nie odnosi żadnego skutku, dopóki funkcja się nie skończy. Jednak kilka funkcji systemowych zachowuje się inaczej i mogą być przerwane przez sygnał. Dotyczy to funkcji read, write i open w odniesieniu do powolnych urządzeń takich, jak: terminal, ale już nie plik dyskowy, oraz funkcji wait i pause. We wszystkich tych przypadkach przerwana funkcja systemowa zwraca -1 i umieszcza EINTR w zmiennej errno. Sygnały systemów Unixowych zwykle nie mogą być odkładane na stosie. Ściślej, dla danego procesu w danej chwili nie może istnieć więcej niż jeden zaległy sygnał danego typu, chociaż może występować więcej niż jeden zaległy typ sygnałów. Z tego względu nie powinno się używać sygnałów jako godnej zaufania metody komunikacji. 11

sigsetjmp i siglongjmp Zobacz: skoki.c Czasami w momencie otrzymania sygnału istnieje potrzeba przeskoczenia do poprzedniej pozycji w programie. Zachowanie takie jest możliwe dzięki podprogramom: int sigsetjmp (sigjmp_t env, int savemask); void siglongjmp(sigjmp_t env, int val); Pierwszy zachowuje bieżącą pozycję programu i maskę sygnału przez zapamiętanie środowiska stosu. Drugi przekazuje sterowanie wstecz, do zachowanej pozycji. Pozycja programu jest zachowana w obiekcie typu sigjmp_buf, zdefiniowanym w pliku nagłówkowym <setjmp.h>. Jeżeli w wywołaniu sigsetjmp wartość savemask jest niezerowa, to zachowana zostanie bieżąca maska sygnału, tj. stan i działania związane ze wszystkimi sygnałami, oraz środowisko. Mogą one więc być odtworzone przez siglongjmp. Powrót z sigsetjmp zwróci wartość val, gdy został wywołany z siglongjmp, gdy został wywołany jako kolejna instrukcja sekwencyjna 0. 12

Blokowanie sygnałów Jeżeli program wykonuje odpowiedzialne zadanie, np. aktualizuje bazę danych, należałoby go zabezpieczyć przed przerwaniami w kluczowych sytuacjach. Zamiast ignorowania wszystkich nadchodzących sygnałów proces może blokować sygnały. Oznacza to, że nie będą one obsługiwane, dopóki proces nie zkończy swojej krytycznej operacji. Funkcją systemową pozwalającą procesowi zablokować konkretny sygnał jest: int sigprocmask(int how, const sigset_t *set const sigset_t *oset); Parametr how informuje jakie działanie wykonać, np. SIG_SETMASK oznacza blokowanie sygnałów ustawionych w drugim parametrze set. Trzeci parametr jest wypełniany bieżącą maską blokowanych sygnałów. Zobacz: blokada.c 13

Wysyłanie sygnałów Do wysyłania sygnałów do procesów służy funkcja: int kill(pid_t pid, int sig); Pierwszy parametr pid określa proces albo procesy, do których będzie wysłany sygnał sig. Ponieważ proces, który wywołuje funkcja kill musi znać PID procesu, do którego wysyła sygnał, funkcji kill używa się najczęściej między procesami powiązanymi, np. procesem rodzicielskim i potomnym. Warto też zauważyć, że proces może wysyłać sygnał do samego siebie. Proces może wysyłać sygnały tylko do takich procesów, których RIUD lub EUID jest taki sam, co procesu wysyłającego. Jak zwykle, proces administratora może wysyłać sygnały do wszystkich procesów. Jeżeli proces zwykłego użytkownika wysyła sygnał do procesu innego użytkownika, to funkcja kill zwraca -1 i umieszcza wartość EPERM w errno. Inne możliwości, to ESRCH: nie ma takiego procesu i EINVAL: sig nie jest ważnym numerem sygnału. 14

Wysyłanie sygnałów cd Parametr pid funkcji kill może przybierać następujące wartości: Jeżeli pid jest równy zero, sygnał będzie wysłany do wszystkich procesów, które należą do tej samej grupy procesów co nadawca. Dotyczy to również nadawcy. Jeżeli pid jest równy -1, a efektywny EUID nie jest administratorem, wtedy sygnał zostanie wysłany do wszystkich procesów z RUID równym EUID nadawcy. Ponownie dotyczy to również nadawcy. Jeżeli pid jest równy -1, a efektywny EUID jest administratorem, wtedy sygnał zostanie wysłany do wszystkich procesów z wyjątkiem pewnych specjalnych procesów systemowych. Jeżeli pid jest mniejszy niż 0, ale różny od -1, wtedy sygnał zostanie wysłany do wszystkich procesów z GUID równym bezwzględnej wartości pid. Dotyczy również nadawcy, jeśli jego GUID spełnia ten warunek. Zobacz: synchro.c 15

Wysyłanie sygnałów do siebie Do wysyłania sygnału do procesu wywołującego służy funkcja: int raise(int sig); Sygnał o numerze sig jest wysyłany do procesu wywołującego. W przypadku powodzenia funkcja zwraca 0. Do ustawiania zegara alarmu procesu służy funkcja: int alarm(unsigned int sec); Parametr sec podaje czas w sekundach do alarmu. Kiedy czas upłynie, do procesu zostanie wysłany sygnał SIGALRM. Funkcja ta nie powoduje zawieszenia działania procesu, jak sleep(), proces kontynuuje wykonanie, przynajmniej do otrzymania sygnału. Aktywny zegar alarmu przedostaje się także przez wywołanie exec(), natomiast wywołanie funkcji fork() wyłącza zegar alarmu w procesie potomnym. Alarm może być wyłączony za pomocą wywołania funkcji alarm(0), ponieważ wywołania tej funkcji nie są odkładane na stosie, tj. drugie wywołanie zastąpi pierwsze. Jednak zwracany jest wówczas czas pozostający do poprzedniego alarmu. Zobacz: quick.c 16

Funkcja systemowa pause Systemy Unixowe dostarczają również funkcji systemowej: int pause(void); Funkcja ta zawiesza wywołujący proces, aż do otrzymania dowolnego sygnału. Jeżeli sygnał powoduje normalne zakończenie, wtedy zdarzy się tylko to. Jeżeli sygnał jest ignorowany przez proces, pause() ignoruje go również. Jeżeli jednak sygnał jest przechwytywany, to gdy kończy się procedura obsługi przerwania, funkcja zwraca -1 i umieszcza EINTR w errno. Przykład: Program w pliku tml.c używa kolejno funkcji alarm() i pause() do wyświetlenia komunikatu za określoną liczbę sekund. Wywołuje się go następująco: $ tml 10 koniec pracy Zobacz: tml.c 17