So erstellen Sie einen Daemon-Prozess

Lesezeit: 6 Minuten

Benutzeravatar des registrierten Benutzers
registrierter Nutzer

Ich versuche zu verstehen, wie ich mein Programm zu einem Daemon machen kann. Einige Dinge, auf die ich gestoßen bin, sind im Allgemeinen, dass ein Programm die folgenden Schritte ausführt, um ein Daemon zu werden:

  1. Anruf fork().

  2. Rufen Sie im Elternteil an exit(). Dadurch wird sichergestellt, dass der ursprüngliche Elternteil (der Großelternteil des Dämons) davon überzeugt ist, dass sein Kind beendet wurde, dass der Elternteil des Dämons nicht mehr läuft und dass der Dämon kein Prozessgruppenleiter ist. Dieser letzte Punkt ist Voraussetzung für den erfolgreichen Abschluss des nächsten Schrittes.

  3. Anruf setsid(), was dem Daemon eine neue Prozessgruppe und Sitzung gibt, die ihn beide als Leader haben. Dadurch wird auch sichergestellt, dass der Prozess kein zugeordnetes steuerndes Terminal hat (da der Prozess gerade eine neue Sitzung erstellt hat und keine zuweisen wird).

  4. Wechseln Sie über das Arbeitsverzeichnis in das Root-Verzeichnis chdir(). Dies geschieht, weil sich das geerbte Arbeitsverzeichnis irgendwo im Dateisystem befinden kann. Daemons neigen dazu, für die Dauer der Betriebszeit des Systems zu laufen, und Sie möchten kein zufälliges Verzeichnis offen halten und somit verhindern, dass ein Administrator das Dateisystem mit diesem Verzeichnis aushängt.

  5. Schließen Sie alle Dateideskriptoren.

  6. Öffnen Sie die Dateideskriptoren 0, 1 und 2 (Standardeingang, Standardausgang und Standardfehler) und leiten Sie sie um /dev/null.

#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/fs.h>

int main (void)
{
    pid_t pid;
    int i;
    
    /* create new process */
    pid = fork ( );  
    if (pid == -1)  
        return -1;  
    else if (pid != 0)  
        exit (EXIT_SUCCESS);  

    /* create new session and process group */  
    if (setsid ( ) == -1)  
        return -1;  

    /* set the working directory to the root directory */  
    if (chdir ("https://stackoverflow.com/") == -1)  
        return -1;  

    /* close all open files--NR_OPEN is overkill, but works */  
    for (i = 0; i < NR_OPEN; i++)  
        close (i);  

    /* redirect fd's 0,1,2 to /dev/null */  
    open ("/dev/null", O_RDWR);  
    /* stdin */  
    dup (0);  
    /* stdout */  
    dup (0);  
    /* stderror */  
    
    /* do its daemon thing... */  
    
    return 0;  
}

Kann mir jemand einen Link zu vorhandenem Quellcode eines Programms wie Apache geben, damit ich diesen Prozess genauer verstehen kann?

  • Sie können Apache-Quellen abrufen hier.

    – nmichaels

    21. März 2011 um 21:51 Uhr

  • Vielleicht Dämon(3) könnte hilfreich sein. Es besagt im Grunde, dass die benötigte Funktionalität bereits implementiert ist.

    – Vlad

    21. März 2011 um 21:53 Uhr


  • @nmichaels danke für deine Nachricht, eigentlich suche ich nur nach den Zeilen, die es zu einem Daemon machen. Apache nicht speziell. Wenn also einige online sind, ist es einfach, die gesamte Quelle herunterzuladen.

    – Registrierter Nutzer

    21. März 2011 um 21:53 Uhr

  • Bezogen auf stackoverflow.com/questions/3095566/linux-daemonize

    – ninjalj

    21. März 2011 um 22:33 Uhr

  • Der obige Beitrag ist fast 100 % Copy-Paste aus dem Buch Linux-Systemprogrammierung, 2. Auflage – Direkte Kommunikation mit dem Kernel und der C-Bibliothek durch Robert Liebe (Seiten 173, 174). Es wäre schön, wenn @RegisteredUser das erwähnt hätte.

    – patryk.beza

    7. August 2016 um 9:53 Uhr


Benutzeravatar von deadbeef
totes Fleisch

Wenn Sie nach einem sauberen Ansatz suchen, ziehen Sie bitte die Verwendung von Standard-API in Betracht. int daemon(int nochdir, int noclose);. Manpage ziemlich einfach und selbsterklärend. Manpage. Eine gut getestete API übertrifft unsere eigene Implementierung in Bezug auf Portabilität und Stabilität bei weitem.

  • Ich bin froh, dass dies eine ist Antworten jetzt, anstatt in den Kommentaren versteckt zu sein. Vielleicht könnten Sie es ein wenig konkretisieren – Link zum Standard (oder noch besser, ein Link zu einem Tutorial oder Beispiel).

    – RJHunter

    22. Mai 2016 um 10:34 Uhr

  • @deadbeef Diese Antwort ist viel besser als die Ebene nur verlinken Antworten, die vorher vorhanden waren. Aber obwohl es auch ziemlich nah an a ist nur verlinken (jedenfalls würde ich den angegebenen Link für viel stabiler halten). Ich würde versuchen, die Antwort zu verbessern, indem ich ein kurzes Codebeispiel gebe (zumal es keines in der verlinkten Manpage gibt) oder die Zusammenfassung zitiere.

    – πάντα ῥεῖ

    23. Mai 2016 um 17:33 Uhr


  • Beachten Sie, dass Dämon Funktion ist nicht POSIX-konform.

    – patryk.beza

    7. August 2016 um 9:56 Uhr

  • An freedesktop.org/software/systemd/man/daemon.html#SysV%20Daemons es steht geschrieben, dass “die BSD daemon() -Funktion sollte nicht verwendet werden, da sie nur eine Teilmenge davon implementiert [15] Schritte.”

    – oli_arborum

    15. Februar 2017 um 8:10 Uhr

Benutzeravatar von Alok Prasad
Alok Prasad

Unter Linux geht das ganz einfach mit:

int main(int argc, char* argv[])
{
    daemon(0,0);
    while(1)
    {
        sleep(10)
        /*do something*/
    }

    return 0;
}

Benutzeravatar von Rachid K
Rachid K.

Bezüglich des Teils, der die Dateideskriptoren schließt, sind unter Linux die GLIBC’s deamon() Der Dienst leitet lediglich die Dateideskriptoren 0, 1 und 2 um /dev/null verwenden dup2(). Hier ist das Code-Snippet von daemon() in GLIBC 2.34 (Datei misc/daemon.c):

    if (!noclose) {
        struct stat64 st;

        if ((fd = __open_nocancel(_PATH_DEVNULL, O_RDWR, 0)) != -1
            && (__builtin_expect (__fstat64 (fd, &st), 0)
            == 0)) {
            if (__builtin_expect (S_ISCHR (st.st_mode), 1) != 0
#if defined DEV_NULL_MAJOR && defined DEV_NULL_MINOR
                && (st.st_rdev
                == makedev (DEV_NULL_MAJOR, DEV_NULL_MINOR))
#endif
                ) {
                (void)__dup2(fd, STDIN_FILENO);
                (void)__dup2(fd, STDOUT_FILENO);
                (void)__dup2(fd, STDERR_FILENO);
                if (fd > 2)
                    (void)__close (fd);

Schließen Sie alle möglichen geöffneten Dateideskriptoren mit der NR_OPEN konstant (normalerweise gleich 1024) ist nicht zuverlässig, da die Begrenzung der Anzahl geöffneter Dateideskriptoren mit geändert werden kann setrlimit(RLIMIT_NOFILE, ...).
Die aktuell geöffneten Dateideskriptoren sind als symbolische Linknamen in vorhanden /proc/pid/fd Verzeichnis. Hier ist der Inhalt dieses Verzeichnisses aus meiner aktuellen Shell:

$ ls -la /proc/$$/fd
total 0
dr-x------ 2 xxx xxx  0 sept.   4 09:32 .
dr-xr-xr-x 9 xxx xxx  0 sept.   4 09:32 ..
lrwx------ 1 xxx xxx 64 sept.   4 09:32 0 -> /dev/pts/2
lrwx------ 1 xxx xxx 64 sept.   4 09:32 1 -> /dev/pts/2
lrwx------ 1 xxx xxx 64 sept.   4 09:32 2 -> /dev/pts/2
lrwx------ 1 xxx xxx 64 sept.   4 09:41 255 -> /dev/pts/2

Daher könnte eine Servicefunktion, die dieses Verzeichnis für den aktuellen Prozess öffnet, verwendet werden, um nur die tatsächlich geöffneten Dateideskriptoren zu schließen:

#include <sys/types.h>
#include <dirent.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

void close_opened_fds(void)
{
  DIR *dp;
  char proc_fd_dirname[256];
  int my_fd;
  struct dirent *d;
  int fd;

  // Open /proc/<mypid>/fd directory
  snprintf(proc_fd_dirname, sizeof(proc_fd_dirname), "/proc/%d/fd", getpid());
  dp = opendir(proc_fd_dirname);
  if (!dp) {
    return;
  }

  // Get the file descriptor associated to the preceding open
  my_fd = dirfd(dp);

  while((d = readdir(dp))) {

    // Skip '.' and '..' directories
    if (d->d_name[0] == '.') {
      continue;
    }

    fd = atoi(d->d_name);

    // Close the file except if it is the fd of the opened directory
    if (fd != my_fd) {
      close(fd);
    }

  }

  closedir(dp);

}

1415680cookie-checkSo erstellen Sie einen Daemon-Prozess

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy