Christian Seiler: Wie programmiert man einen Daemon in C?

Beitrag lesen

Hallo,

fork(); // abfrage ob erfolgreich ...
[...]
Wenn ich nun aber das Programm in der Konsole starte: ./program so gibt es mir nach wie vor den Prompt erst nach einem strg+C wieder zurück. Da es aber offensichtlich weiterläuft (siehe ps) denke ich, dass es insgesamt aber funktioniert.

Du hast fork() nicht so ganz verstanden: fork() dupliziert den Prozess. Sowohl der duplizierte als auch der ursprüngliche Prozess laufen dann weiter. Beide laufen aber an der gleichen Stelle weiter. Das heißt: Je nach Rückgabewert von fork() kannst Du feststellen, in welchem Prozess Du bist!

Beispiel:

pid_t pid;  
  
/* ... */  
  
pid = fork ();  
  
if (pid < 0) {  
  /* Ein Fehler ist aufgetreten. Zum Beispiel wurde das user-spezifische  
     Prozesslimit erreicht. */  
} else if (pid == 0) {  
  /* Dieser Code wird im Kindprozess ausgeführt. */  
} else {  
  /* Dieser Code wird im Elternprozess ausgeführt, pid ist die PID  
     des Kindprozesses. */  
}  
  
/* Dieser Code wird in beiden Prozessen ausgeführt wenn in den  
   if/else-Blöcken keine return-Anweisung o.ä. enthalten ist. */

Ansonsten war das, was Du sonst so getan hast, gar nicht so verkert: setsid() erstellt eine neue Session (unter UNIX heißt das was anderes als im Webkontext ;-)), umask(0) löscht die aktuelle Umask, chdir ("/") wechselt in das Hauptverzeichnis.

Was Du noch machen solltest:

close (STDIN_FILENO);  
close (STDOUT_FILENO);  
close (STDERR_FILENO);

setsid() sorgt zwar bereits dafür, dass Du kein Kontrollterminal mehr besitzt, aber die Dateideskriptoren sind noch offen - d.h. Du hast das aktuelle Terminal noch geöffnet. Du willst aber als Daemon garantiert nicht auf das Terminal schreiben, von dem Du gestartet wurdest (der soll ja im Hintergrund laufen) - d.h. Du willst die 3 Standarddateideskriptoren schließen.

Sonst fällt mir ad hoc nichts mehr zur Daemonisierung ein, das sollte eigentlich ausreichen, wenn mich nicht alles täuscht. Halt bei jeder Operation noch die Rückgabewerte prüfen, um zu sehen, ob alles geklappt hat. Außer bei close() - es könnte nämlich sein, dass die von vorne herein schon nicht offen sind, dann funktioniert das Schließen natürlich nicht, was in dem Falle aber egal ist.

Viele Grüße,
Christian