Czasami jestem trochę zdezorientowany wszystkimi sygnałami, które może odbierać proces. Jak rozumiem, proces ma domyślny moduł obsługi ( rozmieszczenie sygnałów ) dla każdego z tych sygnałów, ale może zapewnić własny moduł obsługi przez wywołanie sigaction()
.
Oto moje pytanie: co powoduje wysłanie każdego z sygnałów? Zdaję sobie sprawę, że za pomocą -s
parametru można ręcznie wysyłać sygnały do uruchomionych procesów kill
, ale jakie są naturalne okoliczności, w których sygnały te są wysyłane? Na przykład kiedy SIGINT
zostanie wysłany?
Czy istnieją również ograniczenia dotyczące obsługiwanych sygnałów? Czy SIGSEGV
można przetwarzać nawet sygnały i zwracać kontrolę do aplikacji?
Odpowiedzi:
Oprócz wywoływania procesów
kill(2)
niektóre sygnały są wysyłane przez jądro (lub czasami sam proces) w różnych okolicznościach:SIGINT
(proszę wrócić do głównej pętli) na Ctrl+ C,SIGQUIT
(proszę natychmiast wyjść) na Ctrl+ \,SIGTSTP
(proszę zawiesić) na Ctrl+ Z. Klucze można zmienić za pomocąstty
polecenia.SIGTTIN
iSIGTTOU
są wysyłane, gdy proces w tle próbuje odczytać lub zapisać na terminalu sterującym.SIGWINCH
jest wysyłany w celu zasygnalizowania zmiany rozmiaru okna terminala.SIGHUP
przesyłany jest do sygnału, że terminal zniknął (historycznie, ponieważ modem miał godzinie h Ung w górę , w dzisiejszych czasach zazwyczaj dlatego, że zamknął okno emulatora terminala).SIGBUS
dla niewyrównanej pamięci dostępu;SIGSEGV
dostęp do niezapisanej strony;SIGILL
za nielegalną instrukcję (zły kod operacji);SIGFPE
dla instrukcji zmiennoprzecinkowej ze złymi argumentami (npsqrt(-1)
.).SIGALRM
informuje, że upłynął czas ustawiony w procesie. Czasomierze można ustawićalarm
,setitimer
i inni.SIGCHLD
powiadamia proces, że jedno z jego dzieci zmarło.SIGPIPE
jest generowany, gdy proces próbuje zapisać do potoku, gdy koniec odczytu został zamknięty (chodzi o to, że jeśli uruchomiszfoo | bar
ibar
wyjdziesz,foo
zostanie zabity przez aSIGPIPE
).SIGPOLL
(nazywany takżeSIGIO
) powiadamia proces o wystąpieniu zdarzenia pollable. POSIX określa zdarzenia pollable zarejestrowane przezI_SETSIG
ioctl
. Wiele systemów zezwala na zdarzenia pollable na dowolnym deskryptorze pliku ustawionym za pomocąO_ASYNC
fcntl
flagi. Powiązanym sygnałem jestSIGURG
powiadomienie o pilnych danych na urządzeniu (zarejestrowanym przezI_SETSIG
ioctl
) lub gnieździe .SIGPWR
jest wysyłany do wszystkich procesów, gdy UPS sygnalizuje, że nastąpi awaria zasilania.Te listy nie są wyczerpujące. Standardowe sygnały są zdefiniowane w
signal.h
.Większość sygnałów może zostać przechwycona i przetworzona (lub zignorowana) przez aplikację. Jedynymi dwoma przenośnymi sygnałami, których nie można złapać, są
SIGKILL
(po prostu zgiń) iSTOP
(zatrzymaj wykonanie).SIGSEGV
( błąd segmentacji ) i jego kuzynSIGBUS
( błąd magistrali ) można złapać, ale to zły pomysł, chyba że naprawdę wiesz, co robisz. Typową aplikacją do ich przechwytywania jest drukowanie śladu stosu lub innych informacji debugowania. Bardziej zaawansowaną aplikacją jest implementacja pewnego rodzaju zarządzania pamięcią wewnątrzprocesową lub wychwytywanie złych instrukcji w silnikach maszyn wirtualnych.Na koniec pozwól mi wspomnieć o czymś, co nie jest sygnałem. Naciśnięcie Ctrl+ Dna początku wiersza w programie, który odczytuje dane wejściowe z terminala, informuje program, że osiągnięto koniec pliku wejściowego. To nie jest sygnał: jest przesyłany przez interfejs API wejścia / wyjścia. Podobnie jak Ctrl+ Ci przyjaciele, klucz można skonfigurować za pomocą
stty
.źródło
SIGFPE
:, nieco nieintuicyjnie, sygnalizowana jest również przy całkowitym dzieleniu przez zero, a czasem przy przepełnieniu całkowitą ze znakiem.Najpierw odpowiedz na drugie pytanie:
SIGSTOP
iSIGKILL
nie może zostać złapany przez aplikację, ale każdy inny sygnał może nawetSIGSEGV
. Ta właściwość jest przydatna do debugowania - na przykład, przy odpowiedniej obsłudze biblioteki, możesz nasłuchiwaćSIGSEGV
i generować ślad stosu, aby pokazać, gdzie wystąpił ten segfault.Oficjalne słowo (w każdym razie dla systemu Linux) na temat tego, co robi każdy sygnał, jest dostępne po wpisaniu
man 7 signal
z wiersza poleceń systemu Linux. http://linux.die.net/man/7/signal ma te same informacje, ale tabele są trudniejsze do odczytania.Jednak bez pewnego doświadczenia z sygnałami z krótkich opisów trudno jest dowiedzieć się, co robią w praktyce, więc oto moja interpretacja:
Wywołane z klawiatury
SIGINT
dzieje się, gdy uderzaszCTRL+C
.SIGQUIT
jest wywoływany przezCTRL+\
i zrzuca rdzeń.SIGTSTP
zawiesza program po naciśnięciuCTRL+Z
. W przeciwieństwie do tegoSIGSTOP
, jest to możliwe do złapania, co daje programomvi
szansę na zresetowanie terminala do bezpiecznego stanu przed zawieszeniem.Interakcje terminalowe
SIGHUP
(„zawieszanie się”) dzieje się, gdy zamkniesz xterm (lub w inny sposób odłączysz terminal) podczas działania programu.SIGTTIN
iSIGTTOU
wstrzymaj swój program, jeśli będzie próbował czytać lub pisać na terminalu, gdy działa w tle. AbySIGTTOU
tak się stało, myślę, że program musi pisać/dev/tty
, a nie tylko domyślny standard.Wyzwalany przez wyjątek procesora
Oznacza to, że Twój program próbował zrobić coś złego.
SIGILL
oznacza nielegalną lub nieznaną instrukcję procesora. Może się tak zdarzyć, jeśli próbujesz na przykład uzyskać bezpośredni dostęp do portów we / wy procesora.SIGFPE
oznacza, że wystąpił błąd matematyczny sprzętu; najprawdopodobniej program próbował podzielić przez zero.SIGSEGV
oznacza, że twój program próbował uzyskać dostęp do niezapisanego regionu pamięci.SIGBUS
oznacza, że program uzyskał niepoprawny dostęp do pamięci w inny sposób; Nie będę wchodził w szczegóły tego podsumowania.Interakcja procesowa
SIGPIPE
dzieje się, jeśli spróbujesz napisać do potoku po tym, jak czytnik potoku zamknie ich koniec. Zobaczyćman 7 pipe
.SIGCHLD
dzieje się, gdy utworzony proces potomny zostanie zamknięty lub zawieszony (przezSIGSTOP
lub podobny).Przydatny do auto-sygnalizacji
SIGABRT
jest zwykle spowodowany przez program wywołującyabort()
funkcję i domyślnie powoduje zrzut pamięci. Coś w rodzaju „przycisku paniki”.SIGALRM
jest spowodowanyalarm()
wywołaniem systemowym, które spowoduje, że jądro dostarczySIGALRM
do programu po określonej liczbie sekund. Zobaczman 2 alarm
iman 2 sleep
.SIGUSR1
iSIGUSR2
są używane w dowolny sposób. Mogą być przydatne do sygnalizacji między procesami.Wysłane przez administratora
Sygnały te są zwykle wysyłane z wiersza polecenia,
kill
poleceniafg
lubbg
w przypadkuSIGCONT
.SIGKILL
iSIGSTOP
są sygnałami, których nie można zablokować. Pierwszy zawsze kończy proces natychmiast; drugi zawiesza proces.SIGCONT
wznawia zawieszony proces.SIGTERM
jest dającą się złapać wersjąSIGKILL
.źródło
shutdown
polecenie jest używane?SIGTERM
wysyłany jest jako pierwszy, następnie następuje opóźnienie, a następnieSIGKILL
. Zasadniczo w przypadku twardego, natychmiastowego zamknięcia jądro wcale nie musi wysyłać sygnału; może po prostu przestać działać.