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:
-
Anruf fork()
.
-
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.
-
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).
-
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.
-
Schließen Sie alle Dateideskriptoren.
-
Ö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?
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.
Unter Linux geht das ganz einfach mit:
int main(int argc, char* argv[])
{
daemon(0,0);
while(1)
{
sleep(10)
/*do something*/
}
return 0;
}
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);
}
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