Tuesday, July 14, 2009

Write a Linux Daemon


When a daemon starts up, it has to do some low-level housework to get itself ready for its real job. This involves a few steps:

  • Fork off the parent process
  • Change file mode mask (umask)
  • Open any logs for writing
  • Create a unique Session ID (SID)
  • Change the current working directory to a safe place
  • Close standard file descriptors
  • Enter actual daemon code

Listed below is a complete sample daemon that shows all of the steps necessary for setup and execution. To run this, simply compile using gcc, and start execution from the command line. To terminate, use the kill command after finding its PID.

I've also put in the correct include statements for interfacing with the syslog, which is recommended at the very least for sending start/stop/pause/die log statements, in addition to using your own logs with the fopen()/fwrite()/fclose() function calls.

#include <sys/types.h> #include <sys/stat.h> #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <errno.h> #include <unistd.h> #include <syslog.h> #include <string.h>  int main(void) {                  /* Our process ID and Session ID */         pid_t pid, sid;                  /* Fork off the parent process */         pid = fork();         if (pid < 0) {                 exit(EXIT_FAILURE);         }         /* If we got a good PID, then            we can exit the parent process. */         if (pid > 0) {                 exit(EXIT_SUCCESS);         }          /* Change the file mode mask */         umask(0);                          /* Open any logs here */                                  /* Create a new SID for the child process */         sid = setsid();         if (sid < 0) {                 /* Log the failure */                 exit(EXIT_FAILURE);         }                            /* Change the current working directory */         if ((chdir("/")) < 0) {                 /* Log the failure */                 exit(EXIT_FAILURE);         }                  /* Close out the standard file descriptors */         close(STDIN_FILENO);         close(STDOUT_FILENO);         close(STDERR_FILENO);                  /* Daemon-specific initialization goes here */                  /* The Big Loop */         while (1) {            /* Do some task here ... */                        sleep(30); /* wait 30 seconds */         }    exit(EXIT_SUCCESS); }   

From here, you can use this skeleton to write your own daemons. Be sure to add in your own logging (or use the syslog facility), and code defensively, code defensively, code defensively!

No comments: