Unter einem Daemon versteht man einen Prozeß, der im Hintergrund werkelt und irgendwelche Dinge erledigt. Dies ist für Server-Prozesse meistens recht sinnvoll, da sie in der Regel keine Ausgaben erzeugen, die für eine Konsole gedacht sind. Die Programm-Namen, die auf Daemons hinweisen, enden zumeist auf d, wie ftpd, httpd, inetd etc.
Einen Daemon zeichnet aus, daß er sich nach dem Start von der Konsole loslöst und unabhängig im Hintergrund weiter läuft. Meistens führen Daemons ein Logfile, um sich dem Besitzer mitzuteilen. Diese Funktionalität kann auch via syslogd aufgeteilt werden, der Daemon erzeugt die Nachrichten und setzt sie via syslog(3) ab, und der syslog-Daemon übernimmt das Schreiben in die Datei(en).
Um einen Daemon zu erzeugen bedient man sich der Befehle fork(2), setsid(2) und chdir(2). Letzteres dient dazu, daß der Daemon an einem bestimmten Platz "lebt". Es ist z.B. ärgerlich, wenn man ihn in einem Unterverzeichnis gestartet hat, und man dieses dann später nicht entfernen kann, weil es noch in Verwendung ist. Ebenfalls ist es ganz nützlich, wenn stdin, stdout und stderr auf /dev/null umgelegt werden.
Auch sind in diesem Zusammenhang, wie bei anderen Server-Prozessen auch, die Befehle setuid(2) und setgid(2) interessant, um die Rechte einzuschränken, und damit einerseits den potentiellen Schaden, der durch einen Funktionsfehler entstehen kann, zu minimieren, und andererseits dem Benutzer nur die für ihn bestimmten Daten zukommen zu lassen. Außerdem sollte man sich noch chroot(2) ansehen, um das Root-Verzeichnis eines Prozesses zu beeinflussen.
Mancherorts trifft man die Funktion daemon(3) an, die setsid(2), chroot(2) und close(2) bzw. dup(2) aufruft. Portabel ist dies meines Wissens nicht.
Hier ein Beispielprogramm, das nur den Übergang zum Daemon zeigt, auf irgendwelche Funktionalität habe ich hier verzichtet.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <unistd.h>
void start_daemon(void)
{
chdir("/");
setsid();
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
open("/dev/null", O_RDWR);
dup(STDIN_FILENO);
dup(STDIN_FILENO);
for(;;)
sleep(100);
}
int main(int argc, char *argv[])
{
pid_t pid;
if ((pid = fork()) < 0)
{
perror("fork() failed");
return 1;
}
if (pid == 0)
start_daemon();
printf("Child has PID %i.\n", pid);
return 0;
}