Daemons are long running processes that run in the background with no controlling terminal - tty. Use cases for daemons are when the program needs to be available at all times and managed by the scheduler. Popular examples are httpd, sshd, cron, inetd. All of these end in “d”, which is a convention for the name of a daemon. Daemons typically do not have the ability to write to
stderr, and have no means to connect to
stdin because they have no controlling terminal. Having no controlling terminal is a big deal in daemons. If they could connect to a controlling terminal they could be used in nefarious ways. We guarantee the daemon cannot take on a controlling terminal by doing the so-called “double fork”. Usually, output from the daemon is done by writing to log files. These logs are typically written in the in
/var/log directory. Input to a daemon, when necessary, is typically through sockets and signals. Let’s write an example daemon in C that runs on Unix.
Using the Daemon Example
The following code
main.c will call our function
become_daemon() and if the return code is zero - success - the program will be running as a daemon. It’s as simple as that. The program will continue to open up
syslog and will write to the logs every 60 seconds.
C Code to use the Daemon Example
Header file for Daemon Example
We will define a single function
become_daemon() that, when run, will turn the process into a deamon. We need the mechanism to become a daemon simple because during development you don’t want to debug a daemon process unless absolutely necessary. Typically, programs will add a flag that will run the code as a daemon, or, have a flag to turn the daemon off.
Header file for Daemon Example
We will allow our
become_daemon() function to take some flags for some various options. Those options are defined above. In the example we’ll run with no flags by passing in a 0.
C Code for Daemon Example
The daemon C code example isn’t trivial and there are number of concepts needed to be understood. The first concept used by the example is known as the “double fork”. The double fork is the safest way to run a daemon since the resultant daemon has no way to controlling terminal - tty. Also, by doing a second fork we prevent zombie process and the daemon will run as a true orphan process. The end result is the daemon’s parent process will be the
init process and there is no way for the process to open up a controlling terminal.
We’ll leave for another time the theory of sessions, progress groups, parent processes, child processes, orphans and zombies. However, to truly understand a daemon knowing this theory is essential.
Onto the C example for the daemon!
Running the example
If you want the source download become_daemon.
When you run the daemon. It’s 100% uneventful! Nothing happens. You get the prompt back and the daemon goes on living it’s happy life as a daemon process in Unix. Let’s run the example and see what happens.
Analyzing the Daemon Process
Now, with the daemon running let’s look at what’s going on. We can analyize the parent process, if there is a tty, and the parent group and session id.
Daemon Process IDs
ps command, with arguments, lists out the process id, parent process id, parent group id, and session id of our daemon.
We can also see the parent of our daemon is indeed the
Let’s verify our daemon has no tty.
This code will compile and run fine on OS X, however, you will not be able to see logs. The logs should go in
/var/log/system.log but nothing is there. The OS X Operating system now uses
os_log as it would appear and something seems to be stopping logs from happening on OS X. Please comment if you know why?
The Linux Programming Interface Book
This example is heavily influenced by the incredible work of Michael Kerrisk’s groundbreaking book - The Linux Programming Interface. Also, known as TLPI. I highly recommend this book to anyone who is doing system programming, or wants to understand Unix better. This book is truly the Bible of Unix.
Where to go from here?
Now that we have an Example Daemon running the next steps would be to install a signal handler so you can communicte with the daemon and that it properly cleans up when signals such as
SIGKILL are sent to it. Once the signal handler is installed then you can send it messages with the
kill command. Alternatively, you could open a socket and take commands this way.
The second step would be create logging and write to a log file in
/var/log, or, if the system logger works use it, however, see the issues mentioned in OS X.
When developing code that runs as a daemon, it’s highly recommended to be able to test everything first while theh program is not running as a daemon. It’s quite difficult to debug and see what’s going on. However, there are ways.