0% found this document useful (0 votes)
758 views18 pages

Daemon Processes

This document discusses daemon processes in Unix/Linux systems. It begins by defining daemons as long-running background processes that are started during system bootup and terminate during shutdown. It then provides examples of common system daemons like syslogd, crond, and cupsd. The document outlines coding rules for writing daemons, including setting the file mode creation mask, forking to make the parent exit, and calling setsid to create a new session without a controlling terminal. Finally, it provides a daemonize function that implements these rules to properly detach a process from its controlling terminal and parent process.

Uploaded by

sougata88
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
758 views18 pages

Daemon Processes

This document discusses daemon processes in Unix/Linux systems. It begins by defining daemons as long-running background processes that are started during system bootup and terminate during shutdown. It then provides examples of common system daemons like syslogd, crond, and cupsd. The document outlines coding rules for writing daemons, including setting the file mode creation mask, forking to make the parent exit, and calling setsid to create a new session without a controlling terminal. Finally, it provides a daemonize function that implements these rules to properly detach a process from its controlling terminal and parent process.

Uploaded by

sougata88
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 18

Chapter 13.

  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 

PPID  PID  PGID  SID  TTY  TPGID  UID  COMMAND  

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  

1  1403  1  1  ?  -1  0  [nfsd]  


1  1405  1  1  ?  -1  0  [lockd]  
1405  1406  1  1  ?  -1  0  [rpciod]  
1  1853  1853  1853  ?  -1  0  crond  
1  2182  2182  2182  ?  -1  0  /usr/sbin/cupsd  

 
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. 

Figure 13.1. Initialize a daemon process

#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. 

Figure 13.2. The BSD syslog facility

 
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 openlog(const char *ident, int option, int


facility);

void syslog(int priority, const char *format, ...);

void closelog(void);

int setlogmask(int maskpri);

 
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. 

Figure 13.3. The option argument for openlog

option XSI Description


LOG_CONS  •  If the log message can't be sent to syslogd via the UNIX 
domain datagram, the message is written to the console 
instead. 
LOG_NDELAY  •  Open the UNIX domain datagram socket to the syslogd 
daemon immediately; don't wait until the first message is 
logged. Normally, the socket is not opened until the first 
message is logged. 
LOG_NOWAIT  •  Do not wait for child processes that might have been created 
in the process of logging the message. This prevents conflicts 
with applications that catch SIGCHLD, since the application 
might have retrieved the child's status by the time that syslog 
calls wait. 
LOG_ODELAY  •  Delay the open of the connection to the syslogd daemon until 
the first message is logged. 
LOG_PERROR    Write the log message to standard error in addition to sending 
it to syslogd. (Unavailable on Solaris.) 

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. 

Figure 13.4. The facility argument for openlog

facility XSI Description


LOG_AUTH    authorization programs: login, su, getty, ... 
LOG_AUTHPRIV    same as LOG_AUTH, but logged to file with restricted 
permissions 
LOG_CRON    cron and at 
LOG_DAEMON    system daemons: inetd, routed, ... 
LOG_FTP    the FTP daemon (ftpd) 
LOG_KERN    messages generated by the kernel 
LOG_LOCAL0  •  reserved for local use 
LOG_LOCAL1  •  reserved for local use 
LOG_LOCAL2  •  reserved for local use 
LOG_LOCAL3  •  reserved for local use 
LOG_LOCAL4  •  reserved for local use 
LOG_LOCAL5  •  reserved for local use 
LOG_LOCAL6  •  reserved for local use 
LOG_LOCAL7  •  reserved for local use 
LOG_LPR    line printer system: lpd, lpc, ... 
LOG_MAIL    the mail system 
LOG_NEWS    the Usenet network news system 
LOG_SYSLOG    the syslogd daemon itself 
LOG_USER  •  messages from other user processes (default) 
LOG_UUCP    the UUCP system 

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. 

Figure 13.5. The syslog levels (ordered)

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 

openlog("lpd", LOG_PID, LOG_LPR);


syslog(LOG_ERR, "open error for %s: %m", filename);

 
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 

syslog(LOG_ERR | LOG_LPR, "open error for %s: %m", filename);

 
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>

void vsyslog(int priority, const char *format,


va_list arg);

 
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. 

Figure 13.6. Ensure that only one copy of a daemon is running

#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>

#define LOCKFILE "/var/run/daemon.pid"


#define LOCKMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)

extern int lockfile(int);

int
already_running(void)
{
int fd;
char buf[16];

fd = open(LOCKFILE, O_RDWR|O_CREAT, LOCKMODE);


if (fd < 0) {
syslog(LOG_ERR, "can't open %s: %s", LOCKFILE, strerror(errno));
exit(1);
}
if (lockfile(fd) < 0) {
if (errno == EACCES || errno == EAGAIN) {
close(fd);
return(1);
}
syslog(LOG_ERR, "can't lock %s: %s", LOCKFILE, strerror(errno));
exit(1);
}
ftruncate(fd, 0);
sprintf(buf, "%ld", (long)getpid());
write(fd, buf, strlen(buf)+1);
return(0);
}

 
 
   
   

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. 

Figure 13.7. Daemon rereading configuration files

#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;

extern int already_running(void);

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;

if ((cmd = strrchr(argv[0], '/')) == NULL)


cmd = argv[0];
else
cmd++;

/*
* 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

* Make sure only one copy of the daemon is running.


*/
if (already_running()) {
syslog(LOG_ERR, "daemon already running");
exit(1);
}

/*
* 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. 

Figure 13.8. Alternate implementation of daemon rereading configuration files

#include "apue.h"
#include <syslog.h>
#include <errno.h>

extern int lockfile(int);


extern int already_running(void);

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

You might also like