Daemon Processes
Daemon Processes
Daemon Processes Page 1 of 18
Chapter 13. Daemon Processes
Section 13.1. Introduction
Section 13.2. Daemon Characteristics
Section 13.3. Coding Rules
Section 13.4. Error Logging
Section 13.5. Single-Instance Daemons
Section 13.6. Daemon Conventions
Section 13.7. ClientServer Model
Section 13.8. Summary
Exercises
13.1. Introduction
Daemons are processes that live for a long time. They are often started when the system is bootstrapped
and terminate only when the system is shut down. Because they don't have a controlling terminal, we
say that they run in the background. UNIX systems have numerous daemons that perform day-to-day
activities.
In this chapter, we look at the process structure of daemons and how to write a daemon. Since a daemon
does not have a controlling terminal, we need to see how a daemon can report error conditions when
something goes wrong.
For a discussion of the historical background of the term daemon as it applies to computer
systems, see Raymond [1996].
13.2. Daemon Characteristics
Let's look at some common system daemons and how they relate to the concepts of process groups,
controlling terminals, and sessions that we described in Chapter 9. The ps(1) command prints the status
of various processes in the system. There are a multitude of optionsconsult your system's manual for all
the details. We'll execute
ps -axj
file://C:\Users\Unix\AppData\Local\Temp\~hh9D86.htm 11/28/2010
Chapter 13. Daemon Processes Page 2 of 18
under BSD-based systems to see the information we need for this discussion. The -a option shows the
status of processes owned by others, and -x shows processes that don't have a controlling terminal. The
-j option displays the job-related information: the session ID, process group ID, controlling terminal,
and terminal process group ID. Under System Vbased systems, a similar command is ps -efjc. (In an
attempt to improve security, some UNIX systems don't allow us to use ps to look at any processes other
than our own.) The output from ps looks like
0 1 0 0 ? -1 0 init
1 2 1 1 ? -1 0 [keventd]
1 3 1 1 ? -1 0 [kapmd]
0 5 1 1 ? -1 0 [kswapd]
0 6 1 1 ? -1 0 [bdflush]
0 7 1 1 ? -1 0 [kupdated]
1 1009 1009 1009 ? -1 32 portmap
1 1048 1048 1048 ? -1 0 syslogd -m 0
1 1335 1335 1335 ? -1 0 xinetd -
pidfile /var/run/xinetd.pid
We have removed a few columns that don't interest us, such as the accumulated CPU time. The column
headings, in order, are the parent process ID, process ID, process group ID, session ID, terminal name,
terminal process group ID (the foreground process group associated with the controlling terminal), user
ID, and command string.
The system that this ps command was run on (Linux) supports the notion of a session ID,
which we mentioned with the setsid function in Section 9.5. The session ID is simply the
process ID of the session leader. A BSD-based system, however, will print the address of
the session structure corresponding to the process group that the process belongs to
(Section 9.11).
The system processes you see will depend on the operating system implementation. Anything with a
parent process ID of 0 is usually a kernel process started as part of the system bootstrap procedure. (An
exception to this is init, since it is a user-level command started by the kernel at boot time.) Kernel
processes are special and generally exist for the entire lifetime of the system. They run with superuser
privileges and have no controlling terminal and no command line.
file://C:\Users\Unix\AppData\Local\Temp\~hh9D86.htm 11/28/2010
Chapter 13. Daemon Processes Page 3 of 18
Process 1 is usually init, as we described in Section 8.2. It is a system daemon responsible for, among
other things, starting system services specific to various run levels. These services are usually
implemented with the help of their own daemons.
On Linux, the kevenTD daemon provides process context for running scheduled functions in the kernel.
The kapmd daemon provides support for the advanced power management features available with
various computer systems. The kswapd daemon is also known as the pageout daemon. It supports the
virtual memory subsystem by writing dirty pages to disk slowly over time, so the pages can be
reclaimed.
The Linux kernel flushes cached data to disk using two additional daemons: bdflush and kupdated.
The bdflush daemon flushes dirty buffers from the buffer cache back to disk when available memory
reaches a low-water mark. The kupdated daemon flushes dirty pages back to disk at regular intervals to
decrease data loss in the event of a system failure.
The portmapper daemon, portmap, provides the service of mapping RPC (Remote Procedure Call)
program numbers to network port numbers. The syslogd daemon is available to any program to log
system messages for an operator. The messages may be printed on a console device and also written to a
file. (We describe the syslog facility in Section 13.4.)
We talked about the inetd daemon (xinetd) in Section 9.3. It listens on the system's network interfaces
for incoming requests for various network servers. The nfsd, lockd, and rpciod daemons provide
support for the Network File System (NFS).
The cron daemon (crond) executes commands at specified dates and times. Numerous system
administration tasks are handled by having programs executed regularly by cron. The cupsd daemon is
a print spooler; it handles print requests on the system.
Note that most of the daemons run with superuser privilege (a user ID of 0). None of the daemons has a
controlling terminal: the terminal name is set to a question mark, and the terminal foreground process
group is 1. The kernel daemons are started without a controlling terminal. The lack of a controlling
terminal in the user-level daemons is probably the result of the daemons having called setsid. All the
user-level daemons are process group leaders and session leaders and are the only processes in their
process group and session. Finally, note that the parent of most of these daemons is the init process.
13.3. Coding Rules
Some basic rules to coding a daemon prevent unwanted interactions from happening. We state these
rules and then show a function, daemonize, that implements them.
1. The first thing to do is call umask to set the file mode creation mask to 0. The file mode creation
mask that's inherited could be set to deny certain permissions. If the daemon process is going to
create files, it may want to set specific permissions. For example, if it specifically creates files
with group-read and group-write enabled, a file mode creation mask that turns off either of these
file://C:\Users\Unix\AppData\Local\Temp\~hh9D86.htm 11/28/2010
Chapter 13. Daemon Processes Page 4 of 18
permissions would undo its efforts.
2. Call fork and have the parent exit. This does several things. First, if the daemon was started as a
simple shell command, having the parent terminate makes the shell think that the command is
done. Second, the child inherits the process group ID of the parent but gets a new process ID, so
we're guaranteed that the child is not a process group leader. This is a prerequisite for the call to
setsid that is done next.
3. Call setsid to create a new session. The three steps listed in Section 9.5 occur. The process (a)
becomes a session leader of a new session, (b) becomes the process group leader of a new process
group, and (c) has no controlling terminal.
Under System Vbased systems, some people recommend calling fork again at this
point and having the parent terminate. The second child continues as the daemon.
This guarantees that the daemon is not a session leader, which prevents it from
acquiring a controlling terminal under the System V rules (Section 9.6). Alternatively,
to avoid acquiring a controlling terminal, be sure to specify O_NOCTTY whenever
opening a terminal device.
4. Change the current working directory to the root directory. The current working directory
inherited from the parent could be on a mounted file system. Since daemons normally exist until
the system is rebooted, if the daemon stays on a mounted file system, that file system cannot be
unmounted.
Alternatively, some daemons might change the current working directory to some specific
location, where they will do all their work. For example, line printer spooling daemons often
change to their spool directory.
5. Unneeded file descriptors should be closed. This prevents the daemon from holding open any
descriptors that it may have inherited from its parent (which could be a shell or some other
process). We can use our open_max function (Figure 2.16) or the getrlimit function (Section
7.11) to determine the highest descriptor and close all descriptors up to that value.
6. Some daemons open file descriptors 0, 1, and 2 to /dev/null so that any library routines that try
to read from standard input or write to standard output or standard error will have no effect. Since
the daemon is not associated with a terminal device, there is nowhere for output to be displayed;
nor is there anywhere to receive input from an interactive user. Even if the daemon was started
from an interactive session, the daemon runs in the background, and the login session can
terminate without affecting the daemon. If other users log in on the same terminal device, we
wouldn't want output from the daemon showing up on the terminal, and the users wouldn't expect
their input to be read by the daemon.
Example
Figure 13.1 shows a function that can be called from a program that wants to initialize itself as a
daemon.
If the daemonize function is called from a main program that then goes to sleep, we can check the status
of the daemon with the ps command:
file://C:\Users\Unix\AppData\Local\Temp\~hh9D86.htm 11/28/2010
Chapter 13. Daemon Processes Page 5 of 18
$ ./a.out
$ ps -axj
PPID PID PGID SID TTY TPGID UID COMMAND
1 3346 3345 3345 ? -1 501 ./a.out
$ ps -axj | grep 3345
1 3346 3345 3345 ? -1 501 ./a.out
We can also use ps to verify that no active process exists with ID 3345. This means that our daemon is
in an orphaned process group (Section 9.10) and is not a session leader and thus has no chance of
allocating a controlling terminal. This is a result of performing the second fork in the daemonize
function. We can see that our daemon has been initialized correctly.
#include "apue.h"
#include <syslog.h>
#include <fcntl.h>
#include <sys/resource.h>
void
daemonize(const char *cmd)
{
int i, fd0, fd1, fd2;
pid_t pid;
struct rlimit rl;
struct sigaction sa;
/*
* Clear file creation mask.
*/
umask(0);
/*
* Get maximum number of file descriptors.
*/
if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
err_quit("%s: can't get file limit", cmd);
/*
* Become a session leader to lose controlling TTY.
*/
if ((pid = fork()) < 0)
err_quit("%s: can't fork", cmd);
else if (pid != 0) /* parent */
exit(0);
setsid();
/*
* Ensure future opens won't allocate controlling TTYs.
*/
sa.sa_handler = SIG_IGN;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGHUP, &sa, NULL) < 0)
err_quit("%s: can't ignore SIGHUP");
if ((pid = fork()) < 0)
err_quit("%s: can't fork", cmd);
else if (pid != 0) /* parent */
file://C:\Users\Unix\AppData\Local\Temp\~hh9D86.htm 11/28/2010
Chapter 13. Daemon Processes Page 6 of 18
exit(0);
/*
* Change the current working directory to the root so
* we won't prevent file systems from being unmounted.
*/
if (chdir("/") < 0)
err_quit("%s: can't change directory to /");
/*
* Close all open file descriptors.
*/
if (rl.rlim_max == RLIM_INFINITY)
rl.rlim_max = 1024;
for (i = 0; i < rl.rlim_max; i++)
close(i);
/*
* Attach file descriptors 0, 1, and 2 to /dev/null.
*/
fd0 = open("/dev/null", O_RDWR);
fd1 = dup(0);
fd2 = dup(0);
/*
* Initialize the log file.
*/
openlog(cmd, LOG_CONS, LOG_DAEMON);
if (fd0 != 0 || fd1 != 1 || fd2 != 2) {
syslog(LOG_ERR, "unexpected file descriptors %d %d %d",
fd0, fd1, fd2);
exit(1);
}
}
13.4. Error Logging
One problem a daemon has is how to handle error messages. It can't simply write to standard error, since
it shouldn't have a controlling terminal. We don't want all the daemons writing to the console device,
since on many workstations, the console device runs a windowing system. We also don't want each
daemon writing its own error messages into a separate file. It would be a headache for anyone
administering the system to keep up with which daemon writes to which log file and to check these files
on a regular basis. A central daemon error-logging facility is required.
The BSD syslog facility was developed at Berkeley and used widely in 4.2BSD. Most
systems derived from BSD support syslog.
Until SVR4, System V never had a central daemon logging facility.
The syslog function is included as an XSI extension in the Single UNIX Specification.
file://C:\Users\Unix\AppData\Local\Temp\~hh9D86.htm 11/28/2010
Chapter 13. Daemon Processes Page 7 of 18
The BSD syslog facility has been widely used since 4.2BSD. Most daemons use this facility. Figure
13.2 illustrates its structure.
There are three ways to generate log messages:
1. Kernel routines can call the log function. These messages can be read by any user process that
opens and reads the /dev/klog device. We won't describe this function any further, since we're
not interested in writing kernel routines.
2. Most user processes (daemons) call the syslog(3) function to generate log messages. We describe
its calling sequence later. This causes the message to be sent to the UNIX domain datagram
socket /dev/log.
3. A user process on this host, or on some other host that is connected to this host by a TCP/IP
network, can send log messages to UDP port 514. Note that the syslog function never generates
these UDP datagrams: they require explicit network programming by the process generating the
log message.
Refer to Stevens, Fenner, and Rudoff [2004] for details on UNIX domain sockets and UDP sockets.
Normally, the syslogd daemon reads all three forms of log messages. On start-up, this daemon reads a
configuration file, usually /etc/syslog.conf, which determines where different classes of messages
are to be sent. For example, urgent messages can be sent to the system administrator (if logged in) and
printed on the console, whereas warnings may be logged to a file.
file://C:\Users\Unix\AppData\Local\Temp\~hh9D86.htm 11/28/2010
Chapter 13. Daemon Processes Page 8 of 18
Our interface to this facility is through the syslog function.
[View full width]
#include <syslog.h>
void closelog(void);
Returns: previous log priority mask value
Calling openlog is optional. If it's not called, the first time syslog is called, openlog is called
automatically. Calling closelog is also optionalit just closes the descriptor that was being used to
communicate with the syslogd daemon.
Calling openlog lets us specify an ident that is added to each log message. This is normally the name of
the program (cron, inetd, etc.). The option argument is a bitmask specifying various options. Figure
13.3 describes the available options, including a bullet in the XSI column if the option is included in the
openlog definition in the Single UNIX Specification.
file://C:\Users\Unix\AppData\Local\Temp\~hh9D86.htm 11/28/2010
Chapter 13. Daemon Processes Page 9 of 18
LOG_PID • Log the process ID with each message. This is intended for
daemons that fork a child process to handle different requests
(as compared to daemons, such as syslogd, that never call
fork).
The facility argument for openlog is taken from Figure 13.4. Note that the Single UNIX Specification
defines only a subset of the facility codes typically available on a given platform. The reason for the
facility argument is to let the configuration file specify that messages from different facilities are to be
handled differently. If we don't call openlog, or if we call it with a facility of 0, we can still specify the
facility as part of the priority argument to syslog.
file://C:\Users\Unix\AppData\Local\Temp\~hh9D86.htm 11/28/2010
Chapter 13. Daemon Processes Page 10 of 18
We call syslog to generate a log message. The priority argument is a combination of the facility shown
in Figure 13.4 and a level, shown in Figure 13.5. These levels are ordered by priority, from highest to
lowest.
level Description
LOG_EMERG emergency (system is unusable) (highest priority)
LOG_ALERT condition that must be fixed immediately
LOG_CRIT critical condition (e.g., hard device error)
LOG_ERR error condition
LOG_WARNING warning condition
LOG_NOTICE normal, but significant condition
LOG_INFO informational message
LOG_DEBUG debug message (lowest priority)
The format argument and any remaining arguments are passed to the vsprintf function for formatting.
Any occurrence of the two characters %m in the format are first replaced with the error message string
(strerror) corresponding to the value of errno.
The setlogmask function can be used to set the log priority mask for the process. This function returns
the previous mask. When the log priority mask is set, messages are not logged unless their priority is set
in the log priority mask. Note that attempts to set the log priority mask to 0 will have no effect.
The logger(1) program is also provided by many systems as a way to send log messages to the syslog
facility. Some implementations allow optional arguments to this program, specifying the facility, level,
and ident, although the Single UNIX Specification doesn't define any options. The logger command is
intended for a shell script running noninteractively that needs to generate log messages.
Example
In a (hypothetical) line printer spooler daemon, you might encounter the sequence
The first call sets the ident string to the program name, specifies that the process ID should always be
printed, and sets the default facility to the line printer system. The call to syslog specifies an error
condition and a message string. If we had not called openlog, the second call could have been
Here, we specify the priority argument as a combination of a level and a facility.
file://C:\Users\Unix\AppData\Local\Temp\~hh9D86.htm 11/28/2010
Chapter 13. Daemon Processes Page 11 of 18
In addition to syslog, many platforms provide a variant that handles variable argument lists.
[View full width]
#include <syslog.h>
#include <stdarg.h>
All four platforms described in this book provide vsyslog, but it is not included in the
Single UNIX Specification.
Most syslogd implementations will queue messages for a short time. If a duplicate message arrives
during this time, the syslog daemon will not write it to the log. Instead, the daemon will print out a
message similar to "last message repeated N times."
13.5. Single-Instance Daemons
Some daemons are implemented so that only a single copy of the daemon should be running at a time
for proper operation. The daemon might need exclusive access to a device, for example. In the case of
the cron daemon, if multiple instances were running, each copy might try to start a single scheduled
operation, resulting in duplicate operations and probably an error.
If the daemon needs to access a device, the device driver will sometimes prevent multiple opens of the
corresponding device node in /dev. This restricts us to one copy of the daemon running at a time. If no
such device is available, however, we need to do the work ourselves.
The file- and record-locking mechanism provides the basis for one way to ensure that only one copy of a
daemon is running. (We discuss file and record locking in Section 14.3.) If each daemon creates a file
and places a write lock on the entire file, only one such write lock will be allowed to be created.
Successive attempts to create write locks will fail, serving as an indication to successive copies of the
daemon that another instance is already running.
File and record locking provides a convenient mutual-exclusion mechanism. If the daemon obtains a
write-lock on an entire file, the lock will be removed automatically if the daemon exits. This simplifies
recovery, removing the need for us to clean up from the previous instance of the daemon.
Example
The function shown in Figure 13.6 illustrates the use of file and record locking to ensure that only one
copy of a daemon is running.
file://C:\Users\Unix\AppData\Local\Temp\~hh9D86.htm 11/28/2010
Chapter 13. Daemon Processes Page 12 of 18
Each copy of the daemon will try to create a file and write its process ID in it. This will allow
administrators to identify the process easily. If the file is already locked, the lockfile function will fail
with errno set to EACCES or EAGAIN, so we return 1, indicating that the daemon is already running.
Otherwise, we truncate the file, write our process ID to it, and return 0.
We need to truncate the file, because the previous instance of the daemon might have had a process ID
larger than ours, with a larger string length. For example, if the previous instance of the daemon was
process ID 12345, and the new instance is process ID 9999, when we write the process ID to the file, we
will be left with 99995 in the file. Truncating the file prevents data from the previous daemon appearing
as if it applies to the current daemon.
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <syslog.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <sys/stat.h>
int
already_running(void)
{
int fd;
char buf[16];
file://C:\Users\Unix\AppData\Local\Temp\~hh9D86.htm 11/28/2010
Chapter 13. Daemon Processes Page 13 of 18
13.6. Daemon Conventions
Several common conventions are followed by daemons in the UNIX System.
If the daemon uses a lock file, the file is usually stored in /var/run. Note, however, that the
daemon might need superuser permissions to create a file here. The name of the file is usually
name.pid, where name is the name of the daemon or the service. For example, the name of the
cron daemon's lock file is /var/run/crond.pid.
If the daemon supports configuration options, they are usually stored in /etc. The configuration
file is named name.conf, where name is the name of the daemon or the name of the service. For
example, the configuration for the syslogd daemon is /etc/syslog.conf.
Daemons can be started from the command line, but they are usually started from one of the
system initialization scripts (/etc/rc* or /etc/init.d/*). If the daemon should be restarted
automatically when it exits, we can arrange for init to restart it if we include a respawn enTRy
for it in /etc/inittab.
If a daemon has a configuration file, the daemon reads it when it starts, but usually won't look at it
again. If an administrator changes the configuration, the daemon would need to be stopped and
restarted to account for the configuration changes. To avoid this, some daemons will catch SIGHUP
and reread their configuration files when they receive the signal. Since they aren't associated with
terminals and are either session leaders without controlling terminals or members of orphaned
process groups, daemons have no reason to expect to receive SIGHUP. Thus, they can safely reuse
it.
Example
The program shown in Figure 13.7 shows one way a daemon can reread its configuration file. The
program uses sigwait and multiple threads, as discussed in Section 12.8.
We call daemonize from Figure 13.1 to initialize the daemon. When it returns, we call
already_running from Figure 13.6 to ensure that only one copy of the daemon is running. At this
point, SIGHUP is still ignored, so we need to reset the disposition to the default behavior; otherwise, the
thread calling sigwait may never see the signal.
We block all signals, as is recommended for multithreaded programs, and create a thread to handle
signals. The thread's only job is to wait for SIGHUP and SIGTERM. When it receives SIGHUP, the thread
calls reread to reread its configuration file. When it receives SIGTERM, the thread logs a message and
exits.
Recall from Figure 10.1 that the default action for SIGHUP and SIGTERM is to terminate the process.
Because we block these signals, the daemon will not die when one of them is sent to the process.
Instead, the thread calling sigwait will return with an indication that the signal has been received.
#include "apue.h"
#include <pthread.h>
file://C:\Users\Unix\AppData\Local\Temp\~hh9D86.htm 11/28/2010
Chapter 13. Daemon Processes Page 14 of 18
#include <syslog.h>
sigset_t mask;
void
reread(void)
{
/* ... */
}
void *
thr_fn(void *arg)
{
int err, signo;
for (;;) {
err = sigwait(&mask, &signo);
if (err != 0) {
syslog(LOG_ERR, "sigwait failed");
exit(1);
}
switch (signo) {
case SIGHUP:
syslog(LOG_INFO, "Re-reading configuration file");
reread();
break;
case SIGTERM:
syslog(LOG_INFO, "got SIGTERM; exiting");
exit(0);
default:
syslog(LOG_INFO, "unexpected signal %d\n", signo);
}
}
return(0);
}
int
main(int argc, char *argv[])
{
int err;
pthread_t tid;
char *cmd;
struct sigaction sa;
/*
* Become a daemon.
*/
daemonize(cmd);
/*
file://C:\Users\Unix\AppData\Local\Temp\~hh9D86.htm 11/28/2010
Chapter 13. Daemon Processes Page 15 of 18
/*
* Restore SIGHUP default and block all signals.
*/
sa.sa_handler = SIG_DFL;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGHUP, &sa, NULL) < 0)
err_quit("%s: can't restore SIGHUP default");
sigfillset(&mask);
if ((err = pthread_sigmask(SIG_BLOCK, &mask, NULL)) != 0)
err_exit(err, "SIG_BLOCK error");
/*
* Create a thread to handle SIGHUP and SIGTERM.
*/
err = pthread_create(&tid, NULL, thr_fn, 0);
if (err != 0)
err_exit(err, "can't create thread");
/*
* Proceed with the rest of the daemon.
*/
/* ... */
exit(0);
}
Example
As noted in Section 12.8, Linux threads behave differently with respect to signals. Because of this,
identifying the proper process to signal in Figure 13.7 will be difficult. In addition, we aren't guaranteed
that the daemon will react as we expect, because of the implementation differences.
The program in Figure 13.8 shows how a daemon can catch SIGHUP and reread its configuration file
without using multiple threads.
After initializing the daemon, we install signal handlers for SIGHUP and SIGTERM. We can either place
the reread logic in the signal handler or just set a flag in the handler and have the main thread of the
daemon do all the work instead.
#include "apue.h"
#include <syslog.h>
#include <errno.h>
void
reread(void)
file://C:\Users\Unix\AppData\Local\Temp\~hh9D86.htm 11/28/2010
Chapter 13. Daemon Processes Page 16 of 18
{
/* ... */
}
void
sigterm(int signo)
{
syslog(LOG_INFO, "got SIGTERM; exiting");
exit(0);
}
void
sighup(int signo)
{
syslog(LOG_INFO, "Re-reading configuration file");
reread();
}
int
main(int argc, char *argv[])
{
char *cmd;
struct sigaction sa;
if ((cmd = strrchr(argv[0], '/')) == NULL)
cmd = argv[0];
else
cmd++;
/*
* Become a daemon.
*/
daemonize(cmd);
/*
* Make sure only one copy of the daemon is running.
*/
if (already_running()) {
syslog(LOG_ERR, "daemon already running");
exit(1);
}
/*
* Handle signals of interest.
*/
sa.sa_handler = sigterm;
sigemptyset(&sa.sa_mask);
sigaddset(&sa.sa_mask, SIGHUP);
sa.sa_flags = 0;
if (sigaction(SIGTERM, &sa, NULL) < 0) {
syslog(LOG_ERR, "can't catch SIGTERM: %s", strerror(errno));
exit(1);
}
sa.sa_handler = sighup;
sigemptyset(&sa.sa_mask);
sigaddset(&sa.sa_mask, SIGTERM);
sa.sa_flags = 0;
if (sigaction(SIGHUP, &sa, NULL) < 0) {
syslog(LOG_ERR, "can't catch SIGHUP: %s", strerror(errno));
exit(1);
}
file://C:\Users\Unix\AppData\Local\Temp\~hh9D86.htm 11/28/2010
Chapter 13. Daemon Processes Page 17 of 18
/*
* Proceed with the rest of the daemon.
*/
/* ... */
exit(0);
}
13.7. ClientServer Model
A common use for a daemon process is as a server process. Indeed, in Figure 13.2, we can call the
syslogd process a server that has messages sent to it by user processes (clients) using a UNIX domain
datagram socket.
In general, a server is a process that waits for a client to contact it, requesting some type of service. In
Figure 13.2, the service being provided by the syslogd server is the logging of an error message.
In Figure 13.2, the communication between the client and the server is one-way. The client sends its
service request to the server; the server sends nothing back to the client. In the upcoming chapters, we'll
see numerous examples of two-way communication between a client and a server. The client sends a
request to the server, and the server sends a reply back to the client.
13.8. Summary
Daemon processes are running all the time on most UNIX systems. Initializing our own process to run
as a daemon takes some care and an understanding of the process relationships that we described in
Chapter 9. In this chapter, we developed a function that can be called by a daemon process to initialize
itself correctly.
We also discussed the ways a daemon can log error messages, since a daemon normally doesn't have a
controlling terminal. We discussed several conventions that daemons follow on most UNIX systems and
showed examples of how to implement some of these conventions.
Exercises
13.1 As we might guess from Figure 13.2, when the syslog facility is initialized, either by
calling openlog directly or on the first call to syslog, the special device file for the
UNIX domain datagram socket, /dev/log, has to be opened. What happens if the user
process (the daemon) calls chroot before calling openlog?
13.2 List all the daemons active on your system, and identify the function of each one.
file://C:\Users\Unix\AppData\Local\Temp\~hh9D86.htm 11/28/2010
Chapter 13. Daemon Processes Page 18 of 18
13.3 Write a program that calls the daemonize function in Figure 13.1. After calling this
function, call getlogin (Section 8.15) to see whether the process has a login name now
that it has become a daemon. Print the results to a file.
file://C:\Users\Unix\AppData\Local\Temp\~hh9D86.htm 11/28/2010