Question FAQ : Comment transformer mon serveur en demon ?

Il y a 2 approches différentes. La première est d’utiliser le programme inetd pour faire tout le sale boulot pour vous. La secondes est de faire tout le sale boulot vous même.
Si vous utilisez le programme inetd, vous devez utiliser stdin, stdout ou stderr comme socket (ces 3 sockets sont créées par l’appel système dup() à partir de la socket réelle). Vous pouvez les utiliser dans votre code comme si vous utilisiez une socket normale. Le programme inetd va même fermer ces sockets pour vous lorsque vous aurez terminé. Pour plus d’information sur cette méthode, regardez dans l’aide d’inetd.
Si vous souhaitez écrire votre propre serveur, il y a des explications détaillées dans « Unix Network Programming » de Richard Stevens (regardez dans l’entrée de la FAQ « Où puis-je trouver les codes sources d’un livre ? ».
Le code suivant a aussi été récupéré dans le groupe de new « comp.unix.programmer ». Vous pouvez aussi y ajouter du code pour ignorer le signal « SIGPIPE » parce que si ce signal n’est pas traité, votre application pourrait se terminer anormalement.

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/* Global variables */
...
volatile sig_atomic_t keep_going = 1; /* controls program termination */


/* Function prototypes: */
...
void termination_handler (int signum); /* clean up before termination */


int
main (void)
{
  ...

  if (chdir (HOME_DIR))         /* change to directory containing data 
                                    files */
   {
     fprintf (stderr, "`%s': ", HOME_DIR);
     perror (NULL);
     exit (1);
   }

   /* Become a daemon: */
   switch (fork ())
     {
     case -1:                    /* can't fork */
       perror ("fork()");
       exit (3);
     case 0:                     /* child, process becomes a daemon: */
       close (STDIN_FILENO);
       close (STDOUT_FILENO);
       close (STDERR_FILENO);
       if (setsid () == -1)      /* request a new session (job control) */
         {
           exit (4);
         }
       break;
     default:                    /* parent returns to calling process: */
       return 0;
     }

   /* Establish signal handler to clean up before termination: */
   if (signal (SIGTERM, termination_handler) == SIG_IGN)
     signal (SIGTERM, SIG_IGN);
   signal (SIGINT, SIG_IGN);
   signal (SIGHUP, SIG_IGN);

   /* Main program loop */
   while (keep_going)
     {
       ...
     }
   return 0;
}

void
termination_handler (int signum)
{
  keep_going = 0;
  signal (signum, termination_handler);
}