Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger

 << zurück
Linux-UNIX-Programmierung von Jürgen Wolf
Das umfassende Handbuch – 2., aktualisierte und erweiterte Auflage 2006
Buch: Linux-UNIX-Programmierung

Linux-UNIX-Programmierung
1216 S., mit CD, 49,90 Euro
Rheinwerk Computing
ISBN 3-89842-749-8
gp Kapitel 7 Dämonen, Zombies und Prozesse
  gp 7.1 Was ist ein Prozess?
  gp 7.2 Prozesskomponente
    gp 7.2.1 Prozessnummer (PID)
    gp 7.2.2 Prozessnummer des Vaterprozesses (PPID)
    gp 7.2.3 Benutzer- und Gruppennummer eines Prozesses (UID, EUID, GID, EGID)
    gp 7.2.4 Prozessstatus
    gp 7.2.5 Prozesspriorität
    gp 7.2.6 Timesharing-Prozesse
    gp 7.2.7 Prozessauslagerung
    gp 7.2.8 Steuerterminal
  gp 7.3 Prozesse überwachen – ps, top, kpm
  gp 7.4 Lebenszyklus eines Prozesses
  gp 7.5 Umgebungsvariablen eines Prozesses
    gp 7.5.1 Einzelne Umgebungsvariablen abfragen
    gp 7.5.2 Umgebungsvariable verändern oder hinzufügen – putenv() und setenv()
    gp 7.5.3 Löschen von Umgebungsvariablen – unsetenv() und clearenv()
  gp 7.6 Ressourcenlimits eines Prozesses
    gp 7.6.1 Mehr Sicherheit mit Ressourcenlimits
  gp 7.7 Prozesserkennung
  gp 7.8 Erzeugung von Prozessen – fork()
    gp 7.8.1 Pufferung
    gp 7.8.2 Was wird vererbt und was nicht?
    gp 7.8.3 Einen Prozess mit veränderter Priorität erzeugen
  gp 7.9 Warten auf einen Prozess
  gp 7.10 Die exec-Familie
    gp 7.10.1 execl()
    gp 7.10.2 execve()
    gp 7.10.3 execv()
    gp 7.10.4 execle()
    gp 7.10.5 execlp()
    gp 7.10.6 execvp()
    gp 7.10.7 Kindprozesse mit exec-Aufruf überlagern
  gp 7.11 Kommandoaufrufe aus dem Programm – system()
  gp 7.12 Dämonprozesse
    gp 7.12.1 Wie ein Prozess zum Dämon wird ...
    gp 7.12.2 Dämon, sprich mit uns ...
    gp 7.12.3 Protokollieren von Dämonen – syslog()
    gp 7.12.4 syslog() in der Praxis
    gp 7.12.5 Den Dämon, den ich rief ...
  gp 7.13 Rund um die Ausführung von Prozessen
    gp 7.13.1 Einen Dämon beim Booten mit einem init-Skript starten
    gp 7.13.2 Hintergrundprozesse und Jobkontrolle
    gp 7.13.3 Prozesse zeitgesteuert ausführen (cron-Jobs)
  gp 7.14 Zusammenfassung und Ausblick


Rheinwerk Computing

7.12 Dämonprozesse  downtop

Als Dämonprozesse werden Prozesse bezeichnet, die ihre Arbeit unabhängig von der Steuerung des Terminals im Hintergrund ausführen – sprich den Prozessen ist nicht unbedingt ein Controlling Terminal (CTTY) zugeordnet. Auf Ihrem Rechner laufen mindestens ein gutes Dutzend solcher Prozesse. Einige sehr bekannte Dämonen sollen hier nicht unerwähnt bleiben – ohne näher darauf einzugehen (für weitergehende Informationen verwenden Sie bitte entsprechende Manual Pages).

gp  cron – Mit dem cron-Dämon können Sie andere Prozesse (vor allem auch Dämonprozesse) zu einer von Ihnen bestimmten Zeit starten. Der »kleine Bruder« von cron ist atd, der Einmalprozesse behandelt, während cron vorwiegend für wiederkehrende Ereignisse genutzt wird.
gp  xinetd – Dies ist ein Dämon, der andere Netzwerkdämonen startet. (Wird daher auch »Superdämon« genannt.) Wird mit xinetd.conf, /etc/xinet.d/* gesteuert.
gp  lpd, cupsd – der Drucker-Dämon
gp  syslogd, blogd – Dämon zum Protokollieren von Systemmeldungen von anderen Dämonen
gp  klogd – Dämon, der Kernel-Meldungen protokolliert
gp  ftpd, httpd, named, dhcpd, smbd, sshd, NFS – verschiedene Netzwerkdämonen

Hinweis   Eigentlich ist es nicht richtig, von »Dämonen« zu sprechen, da es normalerweise »daemons« lauten müsste. daemons ist ein Abkürzung für disk and execution monitors. Aber hierzulande hat sich der Dämon schon als solcher bildhaft eingeprägt, so dass wir weiterhin bei diesem bleiben.



Rheinwerk Computing

7.12.1 Wie ein Prozess zum Dämon wird ...  downtop

Nachdem Sie gelernt haben, Zombies nicht zu vergessen, werden Sie jetzt einen Dämon erzeugen. Wenn Ihr Nachbar Sie fragt, was Sie den ganzen Tag vor der Kiste machen, erzählen Sie ihm das doch einmal. Bevor Sie erfahren werden, wie Sie programmtechnisch einen eigenen Dämonprozess erzeugen können (ist ganz leicht), sollten Sie sich erst Gedanken machen, wie Sie den Dämon starten wollen. Dafür gibt es ausnahmsweise keine Funktion in C. Angestrebt ist hierfür ein Dämonprozess, der möglichst unabhängig vom Terminal ist und auch so konzipiert sein muss. Denn trifft z. B. ein Unterbrechungssignal in einem Terminal ein, von dem der Dämonprozess gestartet wurde, darf der Dämon davon nicht beeinflusst werden. Somit stehen Ihnen folgende Möglichkeiten zur Verfügung, einen Dämonprozess zu starten – deren Anwendung Sie selbst einschätzen und in Erfahrung bringen müssen.

gp  Sie können selbst von einem Terminal aus einen Dämonprozess im Vorder- oder Hintergrund starten. Dies eignet sich zum Beispiel hervorragend für Probeläufe des Dämons, aber nur bedingt für den Dauereinsatz in einem Mehrbenutzersystem.
gp  Sie können den Dämonprozess auch vom cron-Dämon starten lassen. Ein Dämon ruft also einen Dämon auf. Sie können natürlich auch den at-Befehl verwenden, um den Dämon erst zu einem bestimmten Zeitpunkt zu starten.
gp  Über das Netzwerk können Sie den (x)inetd-Superserver verwenden. Dieser wartet auf Netzwerkanforderungen – die Sie ihm stellen –, worauf dieser tatsächlich den entsprechenden Dämonprozess startet.
gp  Last but not least – das Systeminitialisierungsskript, das beim Booten des Systems sämtliche Dämonen startet. Dieses Skript finden Sie häufig im Verzeichnis /etc, /etc/rc, /etc/init.d usw. – das hängt von der Linux-Distribution ab.

Rheinwerk Computing

7.12.2 Dämon, sprich mit uns ...  downtop

Wenn Sie sich entschieden haben, wie Sie den Dämon starten wollen, müssen Sie noch wissen, wann Ihr Dämon etwas zu sagen hat, wo Sie die Nachrichten »ausgeben« können. Da ein Dämonprozess kein Ausgabeterminal hat, fällt der normale Weg über die Standardausgabe aus. Für solche Zwecke ist der syslog-Dämon zuständig. Der syslog-Dämon wird gewöhnlich ebenfalls beim Booten des Systems über das Initialisierungsskript gestartet und erst wieder beendet, wenn Sie das System (oder syslogd separat) herunterfahren.


Rheinwerk Computing

7.12.3 Protokollieren von Dämonen – syslog()  downtop

Um an die Informationen des syslogd zu kommen, müssen Sie die Funktion syslog() verwenden. syslog() ist zwar keine POSIX-konforme Funktion, doch bieten heute die meisten Linux-/UNIX-Systeme diese Funktion an.

#include <syslog.h>
void syslog(int priority, const char *message, ...);

Das erste Argument priority ist eine Kombination aus dem level und facility. Dabei kann eine Log-Nachricht einen level zwischen einschließlich 0 und 7 haben. Wird kein level angegeben, wird standardmäßig LOG_NOTICE (Level 5) verwendet. Es folgen die möglichen level einer Log-Nachricht.


Tabelle 7.10    Priorität der Nachricht

Level Konstante Bedeutung
0 LOG_EMERG System ist unbrauchbar.
1 LOG_ALERT Dringend irgendwelche Aktionen einleiten
2 LOG_CRIT Kritische Nachrichten
3 LOG_ERR Normaler Fehler
4 LOG_WARNING Warnung
5 LOG_NOTICE Normale, bedeutende Nachricht (Standard)
6 LOG_INFO Normale Nachricht
7 LOG_DEBUG Unwichtige Nachricht

Der zweite Teil der Kombination von priority ist facility, die zur Identifizierung des Prozesstyps dient, der die Log-Nachricht verschickt hat. Wird hier kein Wert verwendet, gilt als Standardeinstellung LOG_USER. Hier ein Überblick zu den facilitys der Log-Nachrichten.


Tabelle 7.11    Identifizierung, wer die Log-Nachricht verschickt hat

facility Bedeutung
LOG_AUTH Autorisierung
LOG_AUTHPRIV Autorisierung (privat)
LOG_FTP FTP-Dämon
LOG_KERN Kernel-Nachrichten
LOG_USER Nachricht von Usern
LOG_MAIL E-Mail-Subsystem
LOG_DAEMON Verschiedene Dämonen
LOG_SYSLOG syslog-interne Nachrichten
LOG_LPR Drucker-Subsystem
LOG_NEWS News-Subsystem
LOG_UUCP UUCP-Subsystem
LOG_CRON Cron-Dämon
LOG_LOCAL0...7 Reserviert für lokale Verwendung (Eigenbedarf)

Da bei weitem nicht für jedes Programm und jeden Dämon eine extra Konstante zugewiesen werden kann (aus Platzgründen innerhalb des level integers), versehen die meisten Anwendungen ihre Log-Einräge sowieso mit dem eigenen Namen, z. B. mit openlog(), siehe unten.

Mit dem Parameter message geben Sie die Nachricht bei syslog() als eine printf()-typische Formatzeichenkette an.

Wenn ein Prozess die Funktion syslog() aufruft, wird ein UNIX Domain Datagram Socket angelegt und mittels connect() mit dem Pfadnamen des angelegten Sockets (meistens /var/run/log) verbunden. Das Socket bleibt bis zum Ende des Prozesses offen oder bis closelog() aufgerufen wird.

Optional kann auch die Funktion openlog() vor dem ersten Aufruf von syslog() aufgerufen werden:

#include <syslog.h>
void openlog(const char *ident, int option, int facility);

Mit ident legen Sie eine Zeichenkette fest, gewöhnlich der Programmname, die als Indikator für erzeugte Syslog-Nachrichten dient. Folgende optionen und deren Bedeutung können Sie verwenden (es kann auch eine ODER-Verknüpfung für mehrere Optionen verwendet werden).


Tabelle 7.12    Optionen für openlog()

Options Bedeutung
LOG_CONS Ausgabe erfolgt direkt auf die Konsole, sollte ein Fehler mit der Verbindung zum Dämon auftreten.
LOG_NDELAY Verbindung zum Login-Dämon wird sofort aufgebaut (das ist ja implizit bei einer Verbindung). Nicht, wie normalerweise, wenn die erste Nachricht geschrieben wurde.
LOG_PERROR Die Nachricht wird außer an den syslog-Dämon noch zusätzlich an den Fehlerkanal (stderr) geschickt.
LOG_PID Wird ein Programm mehrfach gestartet, ist es sinnvoll, diese Option zu verwenden, da jede syslog-Nachricht eine PID enthält. Sie können damit genau ermitteln, welcher Prozess diese Nachricht geschickt hat. Beispielsweise wenn Sie mit fork() einen Kindprozess zur Erledigung bestimmter Aufgaben erzeugen.

Da beim Aufruf von openlog() gewöhnlich kein UNIX Domain Socket angelegt wird (sondern erst beim ersten syslog()-Aufruf), können Sie mit der Option LOG_NDELAY ein Socket beim Aufruf von openlog() erzeugen. Die Syslog-Typen für den Parameter facility haben Sie bereits kennen gelernt (LOG_KERN,LOG_USER,LOG_MAIL,LOG_DAEMON ...).

In der Praxis könnte somit ein openlog()-Aufruf folgendermaßen aussehen:

openlog("lpd-daemon", LOG_PID, LOG_LPR); 

Hier dient als Kennung »lpd-daemon«. Es wird außerdem immer die Prozess-ID mit ausgegeben (LOG_PID), und als Einrichtung wird das Druckersystem verwendet.

Wenn die Anwendung das Senden der Log-Nachrichten beendet hat, wird closelog() aufgerufen.

#include <syslog.h>
void closelog( void );

Rheinwerk Computing

7.12.4 syslog() in der Praxis  downtop

Ihnen das ganze Thema zum syslogd zu präsentieren, würde hier zu weit gehen. Hierfür sei ein umfassender Blick in die entsprechende Manual Page empfohlen. Aber dennoch will ich Ihnen das Konzept anhand eines einfachen Beispiels demonstrieren. Zu diesem Zwecke benötigen Sie allerdings vollen Zugriff auf den Rechner als root. Sofern Sie (noch) nicht ganz bewandert im Umgang mit Linux sind, rate ich Ihnen, diesen Text zur Sicherheit erst zu lesen. Machen Sie ggf. ein Backup von der Datei /etc/syslog.conf.

Öffnen Sie zuerst die Datei /etc/syslog.conf mit einem Editor. In meinem Fall gehe ich wie folgt vor:

$su
Passwort:******* 
# mcedit /etc/syslog.conf
...
# Mail logging
mail.=debug;mail.=info;mail.=notice  -/var/log/mail/info
mail.=warn                           -/var/log/mail/warnings
mail.err                             -/var/log/mail/errors
...

Sie bekommen nun die komplette Datei in /etc/syslog.conf zu Gesicht. In gekürzter Form soll hier der Log-Eintrag für Mail verwendet werden, z. B. der Eintrag:

mail.=debug;mail.=info;mail.=notice

Dies bedeutet nun, falls der syslog-Dämon eine Nachricht mit der Priorität LOG_DEBUG, LOG_INFO oder LOG_NOTICE und facility=LOG_MAIL erhält, wird diese in die Datei /var/log/mail/info geschrieben.

Liest syslog die Nachricht mit der Priorität LOG_WARNING, wie dies in der nächsten Zeile mit mail.=warn angegeben ist, wird die Ausgabe in /var/log/mail/warnings geschrieben.

Hierzu soll nun ein eigener Typ erstellt werden, der eine einfache Textausgabe auf ein Terminal macht. In diesem Fall auf /dev/tty1 – passen Sie die Angabe bitte Ihren Bedürfnissen an. Ein einfaches »tty« auf der Kommandozeile gibt Ihnen Auskunft darüber, welches Ihr aktueller Terminal ist. Eine eigene Routine können Sie mit LOG_LOCALx (x ist 0 bis 7) verwenden. Nach einer Neuinstallation sollte hierfür noch keiner dieser Einträge belegt sein. Schreiben Sie nun ans Ende der Datei /etc/syslog.conf folgenden Eintrag, und speichern Sie die Datei anschließend ab:

#Testroutine,
local0.=notice                             -/dev/tty1

Das Programm, das zur Identifizierung des Prozesstyps jetzt LOG_LOCAL0 und die Priorität LOG_NOTICE verschickt, kann seine Ausgabe auf das Terminal /dev/tty1 machen. In der Praxis sollten Sie nur Nachrichten mit höchster Priorität (LOG_EMERG) auf ein Terminal ausgeben – worüber Sie letztendlich selbst entscheiden. Idealer ist es, in jedem Fall, die Nachricht in eine Log-Datei zu schreiben, je nach Priorität der Nachricht. Wie Sie die syslog.conf-Datei dementsprechend konfigurieren, entnehmen Sie bitte der Manual Page zu syslogd. Jetzt ein Programmbeispiel, das die eben eingerichtete Identifizierung LOG_LOCAL0 mit der Priorität LOG_NOTICE verwendet.

/* logging.c */
#include <stdio.h>
#include <stdlib.h>
#include <unistd. h.>
#include <syslog.h>
int main(int argc, char **argv) {
   openlog( "logging",
            LOG_PID | LOG_CONS | LOG_NDELAY, LOG_LOCAL0 );
   /* Viel Code */
   /*  Etwas ist passiert -> Schick es an /dev/tty1 */
   syslog(LOG_NOTICE, "Hallo Welt mit syslog\n");
   /* Ende */
   closelog();
   return EXIT_SUCCESS;
}

Vorher müssen Sie den syslog-Dämon neu starten, damit die neue Konfiguration in syslog.conf übernommen wird. Dies können Sie folgendermaßen erledigen (su):

# kill -SIGTERM `cat /var/run/syslogd.pid`
# syslogd 

Oder einfacher:

# kill -HUP `pidof syslogd`

Jetzt können Sie das Listing übersetzen und starten. Von wo Sie die Anwendung starten, ist letztendlich egal. Auf jeden Fall sollten Sie jetzt im Terminal /dev/tty1 (in X zu erreichen mit der Tastenkombination (STRG)+(ALT)+(F1)) etwa folgende Ausgabe erhalten haben:

[Datum] [Uhrzeit] test2[12345]: Hallo Welt mit syslog

Die Ausgabe haben Sie lediglich mit dem Aufruf

syslog(LOG_NOTICE, "Hallo Welt mit syslog\n");

aktiviert. In der Praxis kann syslog() auf der Suche nach Fehlern in Programmen (insbesondere in Programmen, die kein Terminal haben) sehr helfen – was übrigens auch mit dem Debugger GDB möglich ist. Sie können zum Beispiel überwachen, wer gerade wann auf ein bestimmtes Programm zugreift (und wieder Murks gemacht hat):

 openlog("myprogramm", LOG_PID | LOG_CONS, LOG_LOCAL0);
 if( (strcmp(nam1, login_name)) == 0)
   syslog(LOG_NOTICE, "Bing hat sich gerade eingeloggt");
 else if( (strcmp(nam2, login_name)) == 0)
   syslog(LOG_NOTICE, "Bong hat sich gerade eingeloggt");

Bedenken Sie aber, wenn Sie dies auf dem Bildschirm ausgeben wollen, wer das eventuell auch lesen könnte. Linux selbst gibt normalerweise Nachrichten auf dem Bildschirm nur mit der allerhöchsten Priorität aus. Natürlich und vor allem anderen können Sie den syslog-Dämon zum Log(gen) eines selbst geschriebenen Dämons verwenden.


Rheinwerk Computing

7.12.5 Den Dämon, den ich rief ...  toptop

Jetzt, da Sie wissen, wie Sie der Ausgabe von Dämonen Herr werden, sind Sie so weit, selbst welche zu beschwören. Einen fast kompletten Dämonprozess können Sie in den folgenden sieben Schritten einrichten (programmiertechnisch gesehen):

gp  fork() – Erst starten Sie mit fork() einen neuen Kindprozess, worauf Sie anschließend den Elternprozess beenden. Da die Shell nun »glaubt«, dass sich der Elternprozess beendet hat, »denkt« diese, dass die Anwendung fertig ist, und es wird der Kindprozess automatisch im Hintergrund ausgeführt. Die weiteren Schritte beziehen sich jetzt auf den »Kindprozess«.
gp  setsid() – Als Nächstes legen Sie mit der Funktion setsid() eine neue Session (Sitzung) an. Damit wird der Prozess Sessionführer der Session und der Prozessgruppenführer einer neuen Gruppe. Anschließend hat der Prozess kein Terminal (CTTY) mehr. Die Syntax zu setsid():
#include <unistd. h.> pid_t setsid(void);
gp  Signal SIGHUP ignorieren – Da wir jetzt gleich nochmals einen Kindprozess starten und den Elternprozess beenden, müssen Sie das Signal SIGHUP ignorieren, da der zu beendende Prozess der Sessionführer ist und allen anderen Prozessen in der aktuellen Session ein SIGHUP-Signal senden würde. Zwei weitere Signale, die ein Dämon nicht erhalten sollte, sind SIGINT und SIGWINCH.
gp  fork(), die Zweite – Mit einem erneuten fork()-Aufruf gehen Sie sicher, dass der Elternprozess der erste Kindprozess ist, der beendet wird. Dadurch sorgt man dafür, dass ein Dämon nicht automatisch ein Steuerterminal erhält, falls dieser eins öffnen würde. Gerade unter SVR4 kann der Sessionführer ein Terminal öffnen, so dass dieses Terminal zum Steuerterminal wird – genau das wollen Sie ja bei Dämonprozessen vermeiden.
gp  chdir() (und chroot()) – Das Arbeitsverzeichnis des Prozesses sollte nun auf das Root-Verzeichnis abgeändert werden – wobei es hierbei auch Dämonen gibt, die ein anderes Arbeitsverzeichnis verwenden.
gp  umask() – Die Dateimodus-Erstellungsmaske müssen Sie jetzt auf 0 setzen. Damit stellen Sie sicher, wenn der Dämon eine Datei anlegen sollte, dass die Berechtigungsbits der geerbten Dateimodus-Erstellungsmaske keine Auswirkungen auf die neue Datei haben. Manchmal ist aber eine gewisse umask erwünscht ..., es muss also nicht unbedingt umask(0) sein, sondern kann auch umask(022) sein – natürlich vom Dämon selbst zu setzen.
gp  Schließen aller geöffneten Filedeskriptoren mit close(). Ein Elternprozess könnte Ihnen nämlich noch einen störenden Filedeskriptor vererbt haben. Und zur Sicherheit schließen Sie in einer Schleife alle Filedeskriptoren. Wobei hier das Problem entsteht, wie viele Filedeskriptoren verwendet werden. So müssen Sie die Anzahl fast selbst festlegen, da die geöffnete Anzahl unendlich sein kann. Gute Werte sind 32, 64 oder 128 Filedeskriptoren – auch wenn diese nicht offen sind. Eventuell können Sie auch die symbolische Konstante _SC_OPEN_MAX (falls vorhanden) oder OPEN_MAX aus stdio.h (garantiert vorhanden) verwenden.
gp  syslogd mit openlog() aufrufen

Hierzu das Listing, das die einzelnen Schritte demonstriert. Im Beispiel wird auch davon ausgegangen, dass Sie die Schritte im Kapitel zuvor mit dem syslog-Dämon und der Funktion syslog() gemacht haben und sich in der Datei /etc/syslog.conf folgender Eintrag befindet:

#Testroutine,
local0.=notice                             -/dev/tty1

Über Sinn und Unsinn der Ausgabe auf eine Konsole wurde bereits gesprochen. Sie können gerne auch testweise andere Einträge in der Datei /etc/syslog.conf machen. Eine gute Dokumentation können Sie auf der Manual Page von syslogd(8) und syslog.conf(5) nachlesen. Sollten Sie ein anderes Terminal zur Ausgabe verwendet haben, dann verwenden Sie eben dies. Das anschließende Listing startet einen Dämon – legt sich für 15 Sekunden schlafen und beendet diesen wieder – nicht sehr sinnvoll. Alle Ausgaben werden im Beispiel auf das Terminal gemacht, das Sie in der Datei /etc/syslog.conf eingetragen haben.

/* daemon.c */
#include <stdio.h>
#include <unistd. h.>
#include <syslog.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <stdlib.h>
typedef void (*sighandler_t)(int);
static sighandler_t 
handle_signal (int sig_nr, sighandler_t signalhandler) {
   struct sigaction neu_sig, alt_sig;
   neu_sig.sa_handler = signalhandler;
   sigemptyset (&neu_sig.sa_mask);
   neu_sig.sa_flags = SA_RESTART;
   if (sigaction (sig_nr, &neu_sig, &alt_sig) < 0)
      return SIG_ERR;
   return alt_sig.sa_handler;
}
static void start_daemon (const char *log_name, int facility) {
   int i;
   pid_t pid;
   /* Elternprozess beenden, somit haben wir einen Waisen */
   /* dessen sich jetzt vorerst init annimmt              */
   if ((pid = fork ()) != 0)
      exit (EXIT_FAILURE);
   /* Kindprozess wird zum Sessionführer. Misslingt */
   /* dies, kann der Fehler daran liegen, dass der     */
   /* Prozess bereits Sessionführer ist               */
   if (setsid() < 0) {
      printf("%s kann nicht Sessionführer werden!\n",
         log_name);
      exit (EXIT_FAILURE);
   }
   /* Signal SIGHUP ignorieren */
   handle_signal (SIGHUP, SIG_IGN);
   /* Oder einfach: signal(SIGHUP, SIG_IGN) ... */
   /* Das Kind terminieren */
   if ((pid = fork ()) != 0)
      exit (EXIT_FAILURE);
   /* Gründe für das Arbeitsverzeichnis:
    * + core-Datei wird im aktuellen Arbeitsverzeichnis 
    *   hinterlegt.
    * + Damit bei Beendigung mit umount das Dateisystem 
    *   sicher abgehängt werden kann 
    */
   chdir ("/");
   /* Damit wir nicht die Bitmaske vom Elternprozess     */
   /* erben bzw. diese bleibt, stellen wir diese auf 0  */
   umask (0);
   /* Wir schließen alle geöffneten Filedeskriptoren ... */
   for (i = sysconf (_SC_OPEN_MAX); i > 0; i--)
      close (i);
   /* Da unser Dämonprozess selbst kein Terminal für */
   /* die Ausgabe hat....                            */
   openlog ( log_name, 
             LOG_PID | LOG_CONS| LOG_NDELAY, facility );
}
int main (int argc, char **argv) {
   int time   = 15;
   start_daemon ("meinDaemon", LOG_LOCAL0);
   while (1) {
      /* Enlosschleifen: Hier sollte nun der Code für den
       * Daemon stehen, was immer er auch tun soll.
       * Bspw. E-Mails abholen, versenden (was kein 
       * Verweis sein soll, um mit dem Spammen anzufangen); 
       * Bei Fehlermeldungen beispielsweise:
       * if(dies_ist_passiert)
       *    syslog(LOG_WARNING, "dies_ist_Passiert");
       * else if(das_ist_Passiert)
       *    syslog(LOG_INFO, "das_ist_Passiert"); 
       */
      syslog( LOG_NOTICE, "Daemon gestartet ...\n");
      sleep(time);
      syslog( LOG_NOTICE, 
              "Daemon läuft bereits %d Sekunden\n", time );
      break;
   }
   syslog( LOG_NOTICE, "Daemon hat sich beendet\n");
   closelog();
   return EXIT_SUCCESS;
}

Das Programm bei der Ausführung:

$ gcc -o daemon daemon.c
$ ./daemon

Ein Blick auf das Terminal (bei mir /dev/tty1):

Mar 10 07:06:26 linux meinDaemon[2684]: Daemon gestartet ...
Mar 10 07:06:41 linux meinDaemon[2684]: Daemon läuft bereits 15 Sekunden
Mar 10 07:06:41 linux meinDaemon[2684]: Daemon hat sich beendet

Während der Ausführung dürfen Sie gerne die Prozessüberwachung auflisten. Sie finden den Dämonprozess für gewöhnlich mit folgendem Eintrag in der Prozesstabelle:

$ ps xj
 PPID   PID  PGID   SID TTY   TPGID STAT  UID  TIME COMMAND
...
    1  2691  2690  2690 ?        -1 S     500  0:00 ./daemon
...

Sie erkennen den Dämon speziell daran, dass dieser kein Steuerterminal (TTY=?) und als Erkennung des Elternprozesses die PPID 1 (init) hat.

 << zurück
  
  Zum Katalog
Neuauflage: Linux-UNIX-Programmierung
Neuauflage:
Linux-UNIX-
Programmierung

bestellen
 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: Linux-Server






 Linux-Server


Zum Katalog: Das Komplettpaket LPIC-1 & LPIC-2






 Das Komplettpaket
 LPIC-1 & LPIC-2


Zum Katalog: Linux-Hochverfügbarkeit






 Linux-
 Hochverfügbarkeit


Zum Katalog: Shell-Programmierung






 Shell-
 Programmierung


Zum Katalog: Linux Handbuch






 Linux Handbuch


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
Info





Copyright © Rheinwerk Verlag GmbH 2006
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de