Ich bin manchmal etwas verwirrt von all den Signalen, die ein Prozess empfangen kann. So wie ich es verstehe, hat ein Prozess einen Standardhandler (Signal Disposition ) für jedes dieser Signale, aber es kann seinen eigenen Handler bereitstellen, indem es sigaction()
aufruft .
Hier ist also meine Frage:Was bewirkt, dass jedes der Signale gesendet wird? Mir ist klar, dass Sie über das -s
manuell Signale an laufende Prozesse senden können Parameter auf kill
, aber was sind die natürlichen Umstände, unter denen diese Signale gesendet werden? Wann zum Beispiel SIGINT
gesendet werden?
Gibt es auch Einschränkungen, welche Signale verarbeitet werden können? Kann sogar SIGSEGV
Signale verarbeitet und die Kontrolle an die Anwendung zurückgegeben werden?
Akzeptierte Antwort:
Zusätzlich zu Prozessen, die kill(2)
aufrufen , einige Signale werden unter verschiedenen Umständen vom Kernel (oder manchmal vom Prozess selbst) gesendet:
- Terminaltreiber senden Signale, die verschiedenen Ereignissen entsprechen:
- Tastendruckbenachrichtigungen:
SIGINT
(bitte gehen Sie zurück zur Hauptschleife) auf Strg +C ,SIGQUIT
(bitte sofort beenden) auf Strg + ,SIGTSTP
(bitte aussetzen) auf Strg +Z . Die Schlüssel können mitstty
geändert werden Befehl. SIGTTIN
undSIGTTOU
werden gesendet, wenn ein Hintergrundprozess versucht, auf seinem steuernden Terminal zu lesen oder zu schreiben.SIGWINCH
wird gesendet, um zu signalisieren, dass sich die Größe des Terminalfensters geändert hat.SIGHUP
wird gesendet, um zu signalisieren, dass das Terminal verschwunden ist (historisch, weil Ihr Modem h hatte ung oben , heutzutage normalerweise, weil Sie das Terminal-Emulator-Fenster geschlossen haben).
- Tastendruckbenachrichtigungen:
- Einige Prozessor-Traps können ein Signal erzeugen. Die Details sind architektur- und systemabhängig; Hier sind typische Beispiele:
SIGBUS
für einen nicht ausgerichteten Zugriffsspeicher;SIGSEGV
für einen Zugriff auf eine nicht zugeordnete Seite;SIGILL
für eine illegale Anweisung (schlechter Opcode);SIGFPE
für eine Fließkommaanweisung mit schlechten Argumenten (z. B.sqrt(-1)
).
- Eine Reihe von Signalen benachrichtigen den Zielprozess, dass ein Systemereignis aufgetreten ist:
SIGALRM
benachrichtigt, dass ein vom Prozess gesetzter Timer abgelaufen ist. Timer können mitalarm
eingestellt werden ,setitimer
und andere.SIGCHLD
benachrichtigt einen Prozess, dass eines seiner Kinder gestorben ist.SIGPIPE
wird generiert, wenn ein Prozess versucht, in eine Pipe zu schreiben, wenn das Leseende geschlossen wurde (die Idee ist, dass, wenn Siefoo | bar
undbar
Ausgänge,foo
wird von einemSIGPIPE
getötet ).SIGPOLL
(auchSIGIO
genannt ) benachrichtigt den Prozess, dass ein abrufbares Ereignis aufgetreten ist. POSIX spezifiziert abrufbare Ereignisse, die durchI_SETSIG
registriert werdenioctl
. Viele Systeme erlauben abrufbare Ereignisse für jeden Dateideskriptor, der überO_ASYNC
gesetzt wirdfcntl
Flagge. Ein verwandtes Signal istSIGURG
, die über dringende Daten auf einem Gerät benachrichtigt (registriert über denI_SETSIG
ioctl
) oder Steckdose.- Auf einigen Systemen
SIGPWR
wird an alle Prozesse gesendet, wenn die USV einen bevorstehenden Stromausfall signalisiert.
Diese Listen sind nicht vollständig. Standardsignale sind in signal.h
definiert .
Die meisten Signale können von der Anwendung abgefangen und verarbeitet (oder ignoriert) werden. Die einzigen zwei tragbaren Signale, die nicht abgefangen werden können, sind SIGKILL
(einfach sterben) und STOP
(Ausführung stoppen).
SIGSEGV
(Segmentierungsfehler) und sein Cousin SIGBUS
(Busfehler) kann abgefangen werden, aber es ist eine schlechte Idee, es sei denn, Sie wissen wirklich, was Sie tun. Eine gängige Anwendung, um sie abzufangen, ist das Drucken eines Stack-Trace oder anderer Debug-Informationen. Eine fortgeschrittenere Anwendung besteht darin, eine Art prozessinterne Speicherverwaltung zu implementieren oder fehlerhafte Anweisungen in Engines virtueller Maschinen abzufangen.
Lassen Sie mich zum Schluss noch etwas erwähnen, das kein Signal ist. Wenn Sie Strg drücken +D Am Anfang einer Zeile in einem Programm, das Eingaben vom Terminal liest, teilt dies dem Programm mit, dass das Ende der Eingabedatei erreicht ist. Dies ist kein Signal, sondern wird über die Input/Output-API übertragen. Wie Strg +C und Freunde, der Schlüssel kann mit stty
konfiguriert werden .