LDP/LDP/retired/Linux-Daemon-HOWTO.sgml

450 lines
13 KiB
Plaintext

<!doctype linuxdoc system>
<article>
<title>Linux Daemon Writing HOWTO
<author><url url="mailto:dmwatson@comcast.net" name="Devin Watson">
<date>v1.0, May 2004
<abstract>
This document shows how to write a daemon in Linux using GCC. Knowledge
of Linux and a familiarity with C are necessary to use this document.
This HOWTO is Copyright by Devin Watson, under the terms of the BSD License.
</abstract>
<!-- Table of Contents -->
<toc>
<sect>Introduction: What is a Daemon?
<p>A daemon (or service) is a background process is designed to run
autonomously,with little or no user intervention. The Apache web server http
daemon (httpd) is one such example of a daemon. It waits in the background
listening on specific ports and serves up pages, or processes scripts, based on
the type of request.
<p>Creating a daemon in Linux uses a specific set of rules in a given order.
Knowing how they work will help you understand how daemons operate in userland
Linux, but can also operate with calls to the kernel. In fact, a few daemons
interface with kernel modules that work with hardware devices, such as external
controller boards, printers, and PDAs. They are one of the fundamental building
blocks in Linux that give it incredible flexibility and power.
<p>Throughout this HOWTO, a very simple daemon will be built in C. As we go
along, more code will be added, showing the proper order of execution required
to get a daemon up and running.
<sect>Getting Started
<p>First off, you'll need the following packages installed on your Linux machine
to develop daemons, specifically:
<itemize>
<item><tt>GCC 3.2.2 or higher</tt>
<item><tt>Linux Development headers and libraries</tt>
</itemize>
If your system does not already have these installed (not likely, but check
anyway), you'll need them to develop the examples in this HOWTO. To find out
what version of GCC you have installed, use:
<tscreen>
<verb>
gcc --version
</verb>
</tscreen>
<sect>Planning Your Daemon
<sect1>What Is It Going To Do?
<p>A daemon should do one thing, and do it well. That one thing may be as
complex as managing hundreds of mailboxes on multiple domains, or as simple as
writing a report and calling sendmail to mail it out.
<p>In any case, you should have a good plan as to what the daemon should do.
If it is going to interoperate with other daemons (which you may or may not
be writing), this is something else to consider as well.
<sect1>How Much Interaction?
<p>Daemons should never have direct communication with a user through a
terminal. In fact, a daemon shouldn't communicate directly with a user at all.
All communication should pass through some sort of interface (which you may or
may not have to write), which can be as complex as a GTK+ GUI, or as simple as a
signal set.
<sect>Basic Daemon Structure
<p>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:
<itemize>
<item>Fork off the parent process
<item>Change file mode mask (umask)
<item>Open logs for writing
<item>Create a unique Session ID (SID)
<item>Change the current working directory to a safe place
<item>Close standard file descriptors
<item>Enter actual daemon code
</itemize>
<sect1>Forking The Parent Process
<p>A daemon is started either by the system itself or a user in a terminal or
script. When it does start, the process is just like any other executable on the
system. To make it truly autonomous, a <it>child process</it> must be created
where the actual code is executed. This is known as forking, and it uses the
<em>fork()</em> function:
<tscreen>
<verb>
pid_t pid;
/* 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);
}
</verb>
</tscreen>
<p>Notice the error check right after the call to <em>fork()</em>. When writing
a daemon, you will have to code as defensively as possible. In fact, a good
percentage of the total code in a daemon consists of nothing but error
checking.
<p>The <em>fork()</em> function returns either the process id (PID) of the child
process (not equal to zero), or -1 on failure. If the process cannot fork a
child, then the daemon should terminate right here.
<p>If <em>fork()</em> did succeed, the parent process must exit
gracefully. This may seem strange to anyone who hasn't seen it, but by
forking, the child process continues the execution from here on out in
the code.
<sect1>Changing The File Mode Mask (Umask)
<p>In order to write to any files (including logs) created by the daemon, the
file mode mask (umask) must be changed to ensure that they can be written to or
read from properly. This is similar to running umask from the command line, but
we do it programmatically here. We can use the <em>umask()</em> function to
accomplish this:
<tscreen>
<verb>
pid_t pid, sid;
/* Fork off the parent process */
pid = fork();
if (pid < 0) {
/* Log failure (use syslog if possible) */
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);
</verb>
</tscreen>
<p>By setting the umask to 0, we will have full access to the files generated by
the daemon. Even if you aren't planning on using any files, it is a good idea to
set the umask here anyway, just in case you will be accessing files on the
filesystem.
<sect1>Opening Logs For Writing
<p>This part is optional, but it is recommended that you open a log file
somewhere in the system for writing. This may be the only place you can look for
debug information about your daemon.
<sect1>Creating a Unique Session ID (SID)
<p>From here, the child process must get a unique SID from the kernel in order
to operate. Otherwise, the child process becomes an orphan in the system. The
pid_t type, declared in the previous section, is also used to create a new
SID for the child process:
<tscreen>
<verb>
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 any failure */
exit(EXIT_FAILURE);
}
</verb>
</tscreen>
<p>Again, the <em>setsid()</em> function has the same return type
as <em>fork()</em>. We can apply the same error-checking routine here to see if
the function created the SID for the child process.
<sect1>Changing The Working Directory
<p>The current working directory should be changed to some place that is
guaranteed to always be there. Since many Linux distributions do not completely
follow the Linux Filesystem Hierarchy standard, the only directory that is
guaranteed to be there is the root directory (/). We can do this using the
<em>chdir()</em> function:
<tscreen>
<verb>
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 any failure here */
exit(EXIT_FAILURE);
}
/* Change the current working directory */
if ((chdir("/")) < 0) {
/* Log any failure here */
exit(EXIT_FAILURE);
}
</verb>
</tscreen>
<p>Once again, you can see the defensive coding taking place. The
<em>chdir()</em> function returns -1 on failure, so be sure to check for that
after changing to the root directory within the daemon.
<sect1>Closing Standard File Descriptors
<p>One of the last steps in setting up a daemon is closing out the standard file
descriptors (STDIN, STDOUT, STDERR). Since a daemon must not use the terminal,
these file descriptors are both redundant and a potential security hazard.
<p>The <em>close()</em> function can handle this for us:
<tscreen>
<verb>
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 any failure here */
exit(EXIT_FAILURE);
}
/* Change the current working directory */
if ((chdir("/")) < 0) {
/* Log any failure here */
exit(EXIT_FAILURE);
}
/* Close out the standard file descriptors */
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
</verb>
</tscreen>
<p>It's a good idea to stick with the constants defined for the file descriptors,
for the greatest portability between system versions.
<sect>Writing the Daemon Code
<sect1>Initialization
<p>At this point, you have basically told Linux that you're a daemon, so now
it's time to write the actual daemon code. Initialization is the first step
here. Since there can be a multitude of different functions that can be called
here to set up your daemon's task, I won't go too deep into them here.
<p>The big point here is, when initializing anything in a daemon, the same
defensive coding guidelines apply. Be as verbose as possible when writing
either to the syslog or your own logs. Debugging a daemon can be quite difficult
when there isn't enough information available as to the status of the daemon.
<sect1>The Big Loop
<p>A daemon's main code is typically inside an infinite loop. Technically,
it isn't an infinite loop, but it is structured as one:
<tscreen>
<verb>
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 any failures here */
exit(EXIT_FAILURE);
}
/* Change the current working directory */
if ((chdir("/")) < 0) {
/* Log any failures here */
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 */
}
</verb>
</tscreen>
<p>This typical loop is usually a <em>while</em> loop that has an infinite
terminating condition, with a call to <em>sleep</em> in there to make it run at
specified intervals.
<p>Think of it like a heartbeat: when your heart beats, it
performs a few tasks, then waits until the next beat takes place. Many daemons
follow this same methodology.
<sect>Putting It All Together
<sect1>Complete Sample
<p>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 <it>kill</it>
command after finding its PID.
<p>I've also put in the include statements for interfacing with the syslog,
recommended (at the very least) for sending start/stop/pause/die log statements, in
addition to using your own logs with the <em>fopen()</em>/<em>fwrite()</em>/<em>fclose()</em>
function calls.
<tscreen>
<verb>
#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);
}
</verb>
</tscreen>
<p>From here, you should be able to use this skeleton to write your own daemons. Be sure to
add in your own logging (or use the syslog facility). Finally, code defensively,
code defensively, code defensively!
</article>