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 mitsttygeändert werden Befehl. SIGTTINundSIGTTOUwerden gesendet, wenn ein Hintergrundprozess versucht, auf seinem steuernden Terminal zu lesen oder zu schreiben.SIGWINCHwird gesendet, um zu signalisieren, dass sich die Größe des Terminalfensters geändert hat.SIGHUPwird 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:
SIGBUSfür einen nicht ausgerichteten Zugriffsspeicher;SIGSEGVfür einen Zugriff auf eine nicht zugeordnete Seite;SIGILLfür eine illegale Anweisung (schlechter Opcode);SIGFPEfür eine Fließkommaanweisung mit schlechten Argumenten (z. B.sqrt(-1)).
- Eine Reihe von Signalen benachrichtigen den Zielprozess, dass ein Systemereignis aufgetreten ist:
SIGALRMbenachrichtigt, dass ein vom Prozess gesetzter Timer abgelaufen ist. Timer können mitalarmeingestellt werden ,setitimerund andere.SIGCHLDbenachrichtigt einen Prozess, dass eines seiner Kinder gestorben ist.SIGPIPEwird generiert, wenn ein Prozess versucht, in eine Pipe zu schreiben, wenn das Leseende geschlossen wurde (die Idee ist, dass, wenn Siefoo | barundbarAusgänge,foowird von einemSIGPIPEgetötet ).SIGPOLL(auchSIGIOgenannt ) benachrichtigt den Prozess, dass ein abrufbares Ereignis aufgetreten ist. POSIX spezifiziert abrufbare Ereignisse, die durchI_SETSIGregistriert werdenioctl. Viele Systeme erlauben abrufbare Ereignisse für jeden Dateideskriptor, der überO_ASYNCgesetzt wirdfcntlFlagge. Ein verwandtes Signal istSIGURG, die über dringende Daten auf einem Gerät benachrichtigt (registriert über denI_SETSIGioctl) oder Steckdose.- Auf einigen Systemen
SIGPWRwird 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 .