13.1: Introduction
Daemons also call the daemon process (daemon) A long-lived process. They often start when the system is bootstrap and terminate only when the system shuts down. Because they do not have control terminals, they are running in the background. Unixi has a number of daemons that perform daily transaction activities.
13.2: Characteristics of the daemon
View daemon: PS -axj
Attention:
Most daemons run with super user privileges. No daemon has a control terminal and its terminal name is set to question mark (? ), the terminal foreground process group ID is set to-1. The kernel daemon is started with no control terminal. The lack of a control terminal by the user layer daemon may be the result of the daemon calling Setsid. All user layer daemons are the first process of a session for a process group leader process, and are the only processes in these process groups and sessions. Finally, it should be noted that the parent process of most daemons is the init process.
13.3: Programming Rules
There are some basic rules that need to be followed when writing daemons to prevent unwanted interactions. These rules are described below, and then the function daemonize written according to these rules is given.
(1) The first thing to do is to call Umask to set the file mode to create the mask word to 0.
(2) Call fork and then exit the parent process.
(3) Call Setsid to create a new session.
(4) Change the current working directory to the root directory.
(5) Close some unwanted file descriptors.
(6) Some daemons open/dev/null to have file descriptors 0, 1, 2, so any library routine that attempts to read standard input, write standard output, or standard error will have no effect.
Instance:
#include"apue.h"#include<syslog.h>#icnldue<fcntl.h>#include<sys/resource.h>voidDaemonize (Const Char*cmd) { intI, fd0, FD1, FD2; pid_t pid; structRlimit RL; structsigaction sa; //Clear File Creation maskUmask0); //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) {exit (0); } setsid (); //ensure future opens won ' t allocate controlling TtyaSa.sa_handle =sig_ign; Sigemptyset (&sa.sa_mask); Sa.sa_flag=0; if(Sigaction (Sighub, &sa, NULL) <0) {Err_quit ("%s:can ' t ignore Sighub"); } if(PID = fork ()) <0) {Err_quit ("%s:can ' t fork", CMD); } Else if(PID! =0) {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=1024x768; } for(i =0; i < Rl.rlim_max; i++) {close (i); } //attach file descriptors 0, 1, and 2 to/dev/nullfd0 = open ("/dev/null", O_RDWR); FD1= DUP (0); FD2= DUP (0); //Initialize the log fileopenlog (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
The daemon does not have a control terminal, so the output error message needs special handling and can use the syslog logging mechanism.
13.5: Single Instance daemon
For normal operation, some daemons are implemented as single-instance, that is, only one copy of the daemon is run at any one time. The file lock and record lock mechanism is the basis of a method used to ensure that only one copy of a daemon is running. If each daemon creates a file and adds a write lock to the entire file, it allows only one such write lock to be created, so if you attempt to create another such write lock then you will fail to indicate to the subsequent daemon that a copy is running.
File and record locks provide a convenient mechanism for mutual exclusion. If the daemon gets a write lock on the entire file, the write lock is automatically deleted when the daemon terminates. This simplifies the processing required for recovery and removes the need to clean up the previous daemon instance.
Example: The function illustrates the use of file and record locks to 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>#defineLOCKFILE "/var/run/daemon.pid"#defineLockmode (S_irusr | S_IWUSR | S_irgrp | S_ipoth)extern intLockfileint);intAlready_running (void){ intFD; Charbuf[ -]; 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;}
13.6: The ritual of the daemon
In Unix systems, daemons follow the following common conventions:
- If the daemon uses a lock file, the file is usually stored in the/var/run directory.
- If the daemon supports configuration options, the configuration file is usually stored in the/etc directory. The name of the configuration file is usually name.conf, where name is the name of the daemon or service. For example, the configuration file for the syslogd daemon is/etc/syslog.conf.
- Daemons can be started with the command line, but typically they are initiated by one of the system initialization scripts (/etc/rc* or/etc/init.d/*). If it should be restarted automatically when the daemon terminates, we can include the _respawn record entry for the daemon in/etc/inittab, so that init restarts the process.
- If a daemon has a configuration file, it reads the file when the daemon starts, but after that it is not normally viewed.
Example: The procedure shown shows a way for the daemon to reread its configuration file. The program uses sigwait as well as multithreading.
13th Chapter: Daemon Process