June 2005

C Daemon Part I

Sometimes a daemon process (or running service) is needed to check on a condition or facilitate an event. In this article, the beginnings of an eventually more sophisticated daemon based in the C programming language is demonstrated.

As Bare as it Gets

This draft of the daemon process is severely lacking; for good reason. In the first part, the only goal is to get the basic process to fork, mask proper and set itself up to run. There is a basic printf so it is apparent that it is running.

The Makefile

A quick and dirty Makefile is needed to save trouble later on down the road. Again, it is bare bones, no warnings or optimizations just yet:

CC = cc
BARE_DAEMON_BIN = bared
BARE_DAEMON_SRC = bare_daemon_01.c

all: bared

bared:
    ${CC} ${BARE_DAEMON_SRC} -o ${BARE_DAEMON_BIN}

clean:
    rm -f a.out *.core ${BARE_DAEMON_BIN}

Assuming the source file is actually called bare_daemon_01.c and cc plus rm are in $PATH the Makefile will work just fine.

The Bare Source

Needed libs

All that is needed for the bare daemon to run are libs for printing, error handling and basic signal control:

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

First Part of main & fork

Next, the first half of main() assigns the process ID variable then attempts to perform a fork(), note that it checks for pid success:

int main(void) {
    pid_t   pid, sid;

    pid = fork();

    if (pid < 0) {
        exit(EXIT_FAILURE);
    } else if (pid > 0) {
        exit(EXIT_SUCCESS);
    }

Setting the umask & sid

Next a umask call is needed to make sure file access is not necessarily inherited. Additionally, using setsid detaches and puts the daemon into a new session:

    umask(0);

    sid = setsid();
    if (sid < 0) {
        exit(EXIT_FAILURE);
    }

Doing a chdir & while loop

Finally, the daemon changes directory to the root directory and starts the main while loop. The loop sleeps for 10 seconds and prints a message. Last, an exit call for termination:

    if ((chdir("/")) < 0) {
        exit(EXIT_FAILURE);
    }

    while (1) {
        sleep(10);
        printf("tic\n");
    }

    exit(EXIT_SUCCESS);
}

To compile the bare daemon, a simple make will work since it is the only target. Running it is a matter of typing ./bared and waiting 10 seconds for the print. Note the only way to stop the daemon is to grep the process with ps {-ef,aux} (depending on the platform) and killing it.

Full Source

A full copy of the Makefile and source code file can be downloaded. Note that a directory needs to be created for them and the bared.mk file should be moved to Makefile or just included in an empty one.

Summary and C Daemon 2

A simple bare bones fork and detach is easy enough, however, it should be very obvious that the example has some problems. First, it doesn't do anything. That needs to be defined which in of itself will open up a whole new thread of issues such as should it have argument values and what kind? Just as it is, however, is still lacking. Some of the issues that will be tackled in part two of the C daemon series are:

  • Logging, what types and what facility?
  • Better signal handling.
  • Introduction of an interval parameter.
  • A test case purpose.
  • What, if any, modularization should occur?
  • Anything that comes to mind between now and then . . .

In the meantime, give it a try.

Next: C Daemon II Previous: Perl Daemon II