Programmation de démons

Soyez le premier à donner votre avis sur cette source.

Vue 5 572 fois - Téléchargée 274 fois

Description

Déjà, pour ceux qui ne le sauraient pas, un démon à unix ce que les services sont à windows : un programme tournant en arrière-plan, le plus souvent invisibles à l'utilisateur.

J'ai réalisé celui-ci à partir de documentations anglaises trouvées sur google, mais je n'ai pas repris un des exemples expliquant comment s'interfacer avec syslogd pour gérer les logs, il suffit d'un man syslogd pour avoir assez de détails :)

Enfin, comme j'avais pas vu de sources sur ce sujet, je place celle-ci en espérant que çà serve à d'autres...

Source / Exemple :


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/stat.h>

void quitter(int signal) {
  /* libérer ici toute la mémoire allouée par le démon */
  remove("toto.pid"); /* supprimer le fichier contenant le PID */
  exit(EXIT_SUCCESS); /* fin du démon */
}

void executer(void) {
  FILE* f; /* ce fichier contiendra le PID du démon */
  f = fopen("toto.pid", "rt");
  if (f != NULL) { /* le fichier PID existe : une instance est déjà en mémoire */
    fclose(f);
    fprintf(stderr, "le démon est déjà en mémoire (ou a mal été terminé)\n");
    exit(EXIT_FAILURE);
  }
  f = fopen("toto.pid", "wt");
  if (f == NULL) { /* impossible d'écrire le fichier PID */
    fprintf(stderr, "impossible d'écrire le fichier toto.pid\n");
    exit(EXIT_FAILURE);
  }
  fprintf(f, "%i", getpid()); /* on écrit le PID du démon dans le fichier (ex: httpd.pid) */
  fclose(f); /* on ferme le fichier, dont on a plus besoin */
  while (1) {
    sleep(1); /* remplacer le sleep par le code du démon, return pour quitter proprement */
  }
}

int main(void) { /* pas besoin des arguments pour cet exemple ;-) */
  switch (fork()) { /* duplication */
  case -1: /* échec de la duplication */
    fprintf(stderr, "erreur avec fork\n");
    return EXIT_FAILURE;
  case 0: /* duplication réussie : côté fils */
    if (setsid() == -1) { /* on tente de créer un nouveau groupe pour notre démon */
      fprintf(stderr, "erreur avec setsid\n");
      return EXIT_FAILURE;
    }
    if (signal(SIGTERM, quitter) == SIG_ERR) { /* on enregistre les signaux auquels le démon doit répondre */
      fprintf(stderr, "erreur avec signal\n");
      return EXIT_FAILURE;
    }
    chdir("/tmp/"); /* aller dans le répertoire de travail du démon */
    umask(066); /* on modifie les permissions des fichiers créés par le démon en rw------- */
    executer(); /* entrée dans la boucle principale du démon */
    quitter(SIGTERM); /* quitter le démon proprement */
  default: /* duplication réussie : côté père */
    return EXIT_SUCCESS;
  }
}

Conclusion :


Le zip contient toto.c et Makefile. Vous pouvez :
- make clean = nettoyer les fichiers binaires
- make compile = compiler le démon (make tout court marche aussi)
- make run = exécute le démon
- make kill = terminer le démon

Pour vérifier le chargement du démon s'il n'y a pas eu d'erreurs au lancement, faites un ps -x, le démon devrait sommeiller quelque part dans la liste... Et le fichier toto.pid devrait contenir le PID correspondant au démon chargé !

Pas de bug connu, hormis la gestion un peu simpliste des instances.

Codes Sources

A voir également

Ajouter un commentaire Commentaires
Messages postés
103
Date d'inscription
lundi 9 avril 2001
Statut
Membre
Dernière intervention
16 juillet 2008

Salut ! une petite question à quoi sert le fork() ici?
Messages postés
1
Date d'inscription
jeudi 4 septembre 2003
Statut
Membre
Dernière intervention
24 octobre 2003

Désolé pour mon manque de lucidité mais sur le coup du pipe j'ai du mal à suivre, a quoi sert le pipe si le père se meurt?), pouvez me donner quelques explication supplémentaires? D'autre part , ce devrait bien être possible de récupérer le pid du processus sans passer par un fichier, la fonction "ps" le fait bien. Si quelqun a des infos, je suis prenneur ! A+
Messages postés
787
Date d'inscription
samedi 8 juin 2002
Statut
Membre
Dernière intervention
7 juin 2007
1
Je précise que j'ai cherché "man pipe" sur google (je suis sous windows là...), et qu'après quelques résultats salaces, j'ai obtenu l'url http://www.linux-france.org/article/man-fr/man2/pipe-2.html dont le contenu bien qu'instructif, est succint...
Messages postés
787
Date d'inscription
samedi 8 juin 2002
Statut
Membre
Dernière intervention
7 juin 2007
1
Merci pour l'astuce, mais comme je débute en programmation unix, je ne sais pas encore comment utiliser les pipes (enfin, dans un programme j'entend), donc si tu avais un exemple sous la main, çà serait super :p

Quand au fichier il permet surtout de faire un "kill `cat toto.pid`" sans avoir besoin de chercher le PID du démon dans la liste des process, donc je vais probablement le garder, mais je conçois que pour gérer des instances, c'est un peu ... archaïque, lol

A+
Messages postés
8
Date d'inscription
mercredi 23 janvier 2002
Statut
Membre
Dernière intervention
6 septembre 2003

Simpa ton code mais j'ai juste une petite critique....
Pour voir si une instance du demon est deja lancé, il faut utiliser un
pipe et nom un fichier...
Utilise la fonction pipe();
...

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.