3.8. Prozesse und Dämonen

FreeBSD ist ein Multitasking-Betriebssystem. Jedes Programm, das zu irgendeiner Zeit läuft wird als Prozess bezeichnet. Jedes laufende Kommando startet mindestens einen neuen Prozess. Dazu gibt es eine Reihe von Systemprozessen, die von FreeBSD ausgeführt werden.

Jeder Prozess wird durch eine eindeutige Nummer identifiziert, die Prozess-ID (PID) genannt wird. Prozesse haben ebenso wie Dateien einen Besitzer und eine Gruppe, die festlegen, welche Dateien und Geräte der Prozess benutzen kann. Die meisten Prozesse haben auch einen Elternprozess, der sie gestartet hat. Beispielsweise ist die Shell ein Prozess. Jedes in Shell gestartete Kommando ist dann ein neuer Prozess, der die Shell als Elternprozess besitzt. Die Ausnahme hiervon ist ein spezieller Prozess namens init(8), der beim booten immer als erstes gestartet wird und der immer die PID 1 hat.

Manche Programme erwarten keine Eingaben vom Benutzer und lösen sich bei erster Gelegenheit von ihrem Terminal. Ein Webserver zum Beispiel antwortet auf Web-Anfragen und nicht auf Benutzereingaben. Mail-Server sind ein weiteres Beispiel für diesen Typ von Anwendungen. Diese Programme sind als Dämonen bekannt. Der Begriff Dämon stammt aus der griechischen Mythologie und bezeichnet ein Wesen, das weder gut noch böse ist und welches unsichtbar nützliche Aufgaben verrichtet. Deshalb ist das BSD Maskottchen dieser fröhlich aussehende Dämon mit Turnschuhen und Dreizack.

Programme, die als Dämon laufen, werden entsprechend einer Konvention mit einem d am Ende benannt. BIND steht beispielsweise für Berkeley Internet Name Domain, das tatsächlich laufende Programm heißt aber named. Der Apache Webserver wird httpd genannt und der Druckerspool-Dämon heißt lpd(8). Dies ist allerdings nur eine Konvention. Der Dämon der Anwendung Sendmail heißt beispielsweise sendmail und nicht maild.

3.8.1. Prozesse beobachten

Um die Prozesse auf dem System zu sehen, benutzen Sie ps(1) und top(1). Eine statische Liste der laufenden Prozesse, deren PIDs, Speicherverbrauch und die Kommandozeile, mit der sie gestartet wurden, erhalten Sie mit ps(1). Um alle laufenden Prozesse in einer Anzeige zu sehen, die alle paar Sekunden aktualisiert wird, so dass Sie interaktiv sehen können was der Computer macht, benutzen Sie top(1).

In der Voreinstellung zeigt ps(1) nur die laufenden Prozesse, die dem Benutzer gehören. Zum Beispiel:

% ps
 PID TT  STAT    TIME COMMAND
8203  0  Ss   0:00.59 /bin/csh
8895  0  R+   0:00.00 ps

Die Ausgabe von ps(1) ist in einer Anzahl von Spalten organisiert. Die PID Spalte zeigt die Prozess-ID. PIDs werden von 1 beginnend bis 99999 zugewiesen und fangen wieder von vorne an. Ist eine PID bereits vergeben, wird diese allerdings nicht erneut vergeben. Die Spalte TT zeigt den Terminal, auf dem das Programm läuft. STAT zeigt den Status des Programms und TIME gibt die Zeit an, die das Programm auf der CPU gelaufen ist. Dies ist nicht unbedingt die Zeit, die seit dem Start des Programms vergangen ist, da die meisten Programme hauptsächlich auf bestimmte Dinge warten, bevor sie wirklich CPU-Zeit verbrauchen. Unter der Spalte COMMAND findet sich schließlich die Kommandozeile, mit der das Programm gestartet wurde.

ps(1) besitzt viele Optionen, um die angezeigten Informationen zu beeinflussen. Eine nützliche Kombination ist auxww. a zeigt Information über alle laufenden Prozesse aller Benutzer. Der Name des Besitzers des Prozesses, sowie Informationen über den Speicherverbrauch werden mit u angezeigt. x zeigt auch Dämonen-Prozesse an, und ww veranlasst ps(1) die komplette Kommandozeile für jeden Befehl anzuzeigen, anstatt sie abzuschneiden, wenn sie zu lang für die Bildschirmausgabe wird.

Die Ausgabe von top(1) sieht in etwa so aus:

% top
last pid:  9609;  load averages:  0.56,  0.45,  0.36              up 0+00:20:03  10:21:46
107 processes: 2 running, 104 sleeping, 1 zombie
CPU:  6.2% user,  0.1% nice,  8.2% system,  0.4% interrupt, 85.1% idle
Mem: 541M Active, 450M Inact, 1333M Wired, 4064K Cache, 1498M Free
ARC: 992M Total, 377M MFU, 589M MRU, 250K Anon, 5280K Header, 21M Other
Swap: 2048M Total, 2048M Free

  PID USERNAME    THR PRI NICE   SIZE    RES STATE   C   TIME   WCPU COMMAND
  557 root          1 -21  r31   136M 42296K select  0   2:20  9.96% Xorg
 8198 dru           2  52    0   449M 82736K select  3   0:08  5.96% kdeinit4
 8311 dru          27  30    0  1150M   187M uwait   1   1:37  0.98% firefox
  431 root          1  20    0 14268K  1728K select  0   0:06  0.98% moused
 9551 dru           1  21    0 16600K  2660K CPU3    3   0:01  0.98% top
 2357 dru           4  37    0   718M   141M select  0   0:21  0.00% kdeinit4
 8705 dru           4  35    0   480M    98M select  2   0:20  0.00% kdeinit4
 8076 dru           6  20    0   552M   113M uwait   0   0:12  0.00% soffice.bin
 2623 root          1  30   10 12088K  1636K select  3   0:09  0.00% powerd
 2338 dru           1  20    0   440M 84532K select  1   0:06  0.00% kwin
 1427 dru           5  22    0   605M 86412K select  1   0:05  0.00% kdeinit4

Die Ausgabe ist in zwei Abschnitte geteilt. In den ersten fünf Kopfzeilen finden sich die zuletzt zugeteilte PID, die Systemauslastung (engl. load average), die Systemlaufzeit (die Zeit seit dem letzten Reboot) und die momentane Zeit. Die weiteren Zahlen im Kopf beschreiben wie viele Prozesse momentan laufen, wie viel Speicher und Swap verbraucht wurde und wie viel Zeit das System in den verschiedenen CPU-Modi verbringt. Wenn das ZFS-Kernelmodul geladen ist, dann zeigt die Zeile ARC, wie viele Daten aus dem Cache gelesen wurden.

Darunter befinden sich einige Spalten mit ähnlichen Informationen wie in der Ausgabe von ps(1), beispielsweise die PID, den Besitzer, die verbrauchte CPU-Zeit und das Kommando, das den Prozess gestartet hat. top(1) zeigt in zwei Spalten den Speicherverbrauch des Prozesses an. Die erste Spalte gibt den gesamten Speicherverbrauch des Prozesses an, in der zweiten Spalte wird der aktuelle Verbrauch angegeben.

Die Anzeige wird von top(1) automatisch alle zwei Sekunden aktualisiert. Ein anderer Intervall kann mit -s spezifiziert werden.

3.8.2. Stoppen von Prozessen

Eine Möglichkeit mit einem laufenden Prozess zu kommunizieren, ist über das Versenden von Signalen mittels kill(1). Es gibt eine Reihe von verschiedenen Signalen. Manche haben eine feste Bedeutung, während andere in der Dokumentation der Anwendung beschrieben sind. Ein Benutzer kann ein Signal nur an einen Prozess senden, welcher ihm gehört. Wird versucht ein Signal an einen Prozess eines anderen Benutzers zu senden, resultiert dies in einem Zugriffsfehler mangels fehlender Berechtigungen. Die Ausnahme ist der root-Benutzer, welcher jedem Prozess Signale senden kann.

FreeBSD kann auch ein Signal an einen Prozess senden. Wenn eine Anwendung schlecht geschrieben ist und auf Speicher zugreift, auf den sie nicht zugreifen soll, so sendet FreeBSD dem Prozess das Segmentation Violation Signal (SIGSEGV). Wenn eine Anwendung programmiert wurde, den alarm(3) Systemaufruf zu benutzen, um nach einiger Zeit benachrichtigt zu werden, bekommt sie das Alarm-Signal (SIGALRM) gesendet.

Zwei Signale können benutzt werden, um einen Prozess zu stoppen: SIGTERM und SIGKILL. SIGTERM fordert den Prozess höflich zum Beenden auf. Der Prozess kann das Signal abfangen und hat dann Gelegenheit Logdateien zu schließen und die Aktion, die er durchführte, abzuschließen. In manchen Situationen kann der Prozess SIGTERM ignorieren, wenn er eine Aktion durchführt, die nicht unterbrochen werden darf.

SIGKILL kann von keinem Prozess ignoriert werden. Wird einem Prozess SIGKILL geschickt, dann wird FreeBSD diesen sofort beenden[1].

Andere häufig verwendete Signale sind SIGHUP, SIGUSR1 und SIGUSR2. Da diese Signale für allgemeine Zwecke vorgesehen sind, werden verschiedene Anwendungen unterschiedlich auf diese Signale reagieren.

Ändern Sie beispielsweise die Konfiguration eines Webservers, so muss dieser angewiesen werden, seine Konfiguration neu zu lesen. Ein Neustart von httpd würde dazu führen, dass der Server für kurze Zeit nicht erreichbar ist. Senden Sie dem Dämon stattdessen das SIGHUP-Signal. Es sei erwähnt, dass verschiedene Dämonen sich anders verhalten. Lesen Sie die Dokumentation des entsprechenden Dämonen um zu überprüfen, ob der Dämon bei einem SIGHUP die gewünschten Ergebnisse erzielt.

Prozedur 3.1. Verschicken von Signalen

Das folgende Beispiel zeigt, wie Sie inetd(8) ein Signal schicken. Die Konfigurationsdatei von inetd(8) ist /etc/inetd.conf. Diese Konfigurationsdatei liest inetd(8) ein, wenn er SIGHUP empfängt.

  1. Suchen Sie mit pgrep(1) die PID des Prozesses, dem Sie ein Signal schicken wollen. In diesem Beispiel ist die PID von inetd(8) 198:

    % pgrep -l inetd
    198 inetd -wW
  2. Benutzen Sie kill(1), um ein Signal zu senden. Da inetd(8) dem Benutzer root gehört, müssen Sie zuerst mit su(1) root werden:

    % su
    Password:
    # /bin/kill -s HUP 198

    kill(1) wird, wie andere UNIX® Kommandos auch, keine Ausgabe erzeugen, wenn das Kommando erfolgreich war. Wird versucht, einem Prozess der nicht dem Benutzer gehört, ein Signal zu senden, dann wird die Meldung kill: PID: Operation not permitted ausgegeben. Ein Tippfehler bei der Eingabe der PID führt dazu, dass das Signal an einen falschen Prozess gesendet wird, was zu negativen Ergebnissen führen kann, oder das Signal wird an eine PID gesendet die derzeit nicht in Gebrauch ist, was zu dem Fehler kill: PID: No such process führt.

    Warum sollte man /bin/kill benutzen?:

    Viele Shells stellen kill als internes Kommando zur Verfügung, das heißt die Shell sendet das Signal direkt, anstatt /bin/kill zu starten. Beachten Sie, dass die unterschiedlichen Shells eine andere Syntax benutzen, um die Namen der Signale anzugeben. Anstatt jede Syntax zu lernen, kann es einfacher sein, /bin/kill direkt aufzurufen.

Beim Versenden von anderen Signalen, ersetzen Sie TERM oder KILL in der Kommandozeile mit dem Namen des Signals.

Wichtig:

Das zufällige Beenden eines Prozesses kann gravierende Auswirkungen haben. Insbesondere init(8), mit der PID 1, ist ein Spezialfall. /bin/kill -s KILL 1 ist ein schneller, jedoch nicht empfohlener Weg, das System herunterzufahren. Überprüfen Sie die Argumente von kill(1) immer zweimal bevor Sie Return drücken.



[1] Es gibt Fälle, in denen ein Prozess nicht unterbrochen werden kann. Wenn ein Prozess zum Beispiel eine Datei von einem anderen Rechner auf dem Netzwerk liest und dieser Rechner nicht erreichbar ist, dann ist der Prozess nicht zu unterbrechen. Wenn der Prozess den Lesezugriff nach einem Timeout von typischerweise zwei Minuten aufgibt, dann wird er beendet.

Wenn Sie Fragen zu FreeBSD haben, schicken Sie eine E-Mail an <de-bsd-questions@de.FreeBSD.org>.

Wenn Sie Fragen zu dieser Dokumentation haben, schicken Sie eine E-Mail an <de-bsd-translators@de.FreeBSD.org>.