This article mainly refer to from: Linux system Programming process (eight): Daemon process detailed and create, daemon () use
I. Overview
Daemon (daemon) is a special process running in the background. It is independent of the control terminal and periodically performs a task or waits to handle certain occurrences. It does not require user input to run and provide a service, not to the whole system or to a user program. Most servers in a Linux system are implemented through a daemon process. Common daemon processes include system log process syslogd, Web server httpd, mail server sendmail, and database server mysqld.
The daemon normally starts when the system starts, unless it is forced to terminate until the system shutdown is kept running. Daemons often run as superuser (root) because they want to use a special port (1-1024) or access certain special resources.
The daemon's parent process is the INIT process, because its true parent process exits before the child process after fork, so it is an orphan process inherited by Init. Daemon is non-interactive, no control terminal, so any output, whether it is to standard output device stdout or standard error device stderr output needs special treatment.
The name of the daemon usually ends with D, such as sshd, xinetd, Crond, and so on.
second, the creation of the daemon process
First we need to understand some basic concepts:
Process group: A collection of one or more processes, each of which has a process group ID, which is the process ID session period of process leader: a collection of one or more process groups, each with a single session header process Leader), the session ID is the session first process ID control terminal (controlling terminal): Each session can have a separate control terminal, and the session first process connected to the control terminal is the control process (controlling processes). At this time, with the current terminal interaction is the foreground process group, the rest are the background process group.
A key function is used during the creation of the daemon: Setsid (), which is used to create a new session period.
Give the Linux description of Setsid ()
#include <unistd.h>
pid_t setsid (void);
DESCRIPTION
Setsid () creates a new session if the calling process
group leader. The calling process is the leader of the new session,
the process group leader of the new process Gro Up, and has no control-
Ling tty. The process group ID and session ID of the calling process
are set to the PID of the calling process. The calling process would be the
"only" process in this new process group and the new session.
Return VALUE
in success, the (new) session ID of the calling process is returned.
On error, (pid_t)-1 is returned, and errno are set to indicate the
error.
The process calls the Setsid () function:
First, note that a new session period is created successfully only if the process is not a leader of the process.
(1) Get rid of the control of the original session. The process becomes the first process of a new session session
(2) Get rid of the original process group. Be the leader of a new process group
(3) Get rid of terminal control. If the process has a control terminal before calling Setsid (), then the connection to the terminal is lifted. If the process is the leader of a process group,
This function returns an error.
General steps to create a daemon:
1, fork () Create child process, parent process exit () Exit
This is the first step in creating a daemon. Since the daemon is detached from the control terminal, the completion of the first step will create the illusion that the program has finished running in the shell terminal. All the work that follows is done in the subprocess, and the user can execute other commands in the shell terminal, thereby performing a form of separation from the control terminal and working in the background.
2, call the Setsid () function in the child process to create a new session
After the fork () function is invoked, the child process copies the session period of the parent process completely, process groups, control terminals, and so on, although the parent process exits, but the session, process group, control terminal and so on have not changed, therefore, this is not a true sense of independence, and the Setsid () function can make the process completely independent.
3, again fork () a child process and let the parent process exit.
Now that the process has become a terminal-free session leader, it can reapply to open a control terminal by fork () a child process that is not a session-first process, and the process will not reopen the control terminal. Exits the parent process.
4. Call the ChDir () function in the subprocess so that the root directory "/" becomes the working directory of the child process
This step is also a necessary step. The child process created using fork inherits the current working directory of the parent process. Because the current directory's file system (such as "/MNT/USB") cannot be unloaded while the process is running, this can cause a lot of trouble for future use (for example, the system has to enter Single-user mode for some reason). Therefore, it is common practice to have "/" as the current working directory of the Daemon, so that the above problems can be avoided, and of course, if you have special needs, you can change your current working directory to another path, such as/tmp. The common function of changing the working directory is chdir.
5, call the Umask () function in the child process, set the process's file permission mask to 0
A file permission mask refers to the corresponding bit in the masked file permissions. For example, if a file permission mask is 050, it masks the readable and executable permissions of the filegroup owner. Because the newly created child process using the Fork function inherits the file permission mask of the parent process, this creates a lot of trouble using the file for the child process. Therefore, setting the file permission mask to 0 can greatly enhance the flexibility of the daemon. The function that sets the file permission mask is umask. In this case, the usual method of using Umask (0).
6. Close any unwanted file descriptors in the child process
As with file permission codes, a newly created subprocess with the fork function inherits some files that have already been opened from the parent process. These open files may never be read or written by the daemon, but they consume system resources as well, and may cause the file system in which they reside to not be unloaded.
After the second step above, the daemon has lost contact with the control terminal it belongs to. Therefore, the characters entered from the terminal are unlikely to reach the daemon, and the characters that are output in a regular way (such as printf) in the daemon cannot be displayed on the terminal. Therefore, 3 files with file descriptors of 0, 1, and 2 (often said inputs, outputs, and errors) have lost their value and should be closed.
7, daemon process exit processing
When a user needs an external stop daemon to run, the kill command is often used to stop the daemon. Therefore, the daemon needs coding to achieve the signal signal processing of kill, to achieve the normal exit of the process.
A simple diagram can be a perfect illustration of a few previous steps:
The following program creates a daemon and then uses the daemon to write the current time to the Daemon.log file every other minute, and exits when the daemon receives the sigquit signal.
#include <unistd.h> #include <signal.h> #include <stdlib.h> #include <string.h> #include <
fcntl.h> #include <sys/stat.h> #include <time.h> #include <stdio.h> static bool flag = TRUE;
void Create_daemon ();
void handler (int);
int main () {time_t t;
int FD;
Create_daemon ();
struct Sigaction Act;
Act.sa_handler = handler;
Sigemptyset (&act.sa_mask);
act.sa_flags = 0;
if (Sigaction (Sigquit, &act, NULL)) {printf ("sigaction error.\n");
Exit (0); while (flag) {FD = open ("/home/mick/daemon.log", O_wronly | O_creat |
O_append, 0644);
if (fd = = 1) {printf ("open error\n");
} t = time (0);
Char *buf = asctime (localtime (&t));
Write (FD, buf, strlen (BUF));
Close (FD);
Sleep (60);
return 0;
} void Handler (int sig) {printf ("I got a signal%d\ni ' m quitting.\n", SIG);
Flag = false;
} void Create_daemon () {pid_t pid;
PID = fork ();
if (PID = = 1) {printf ("fork error\n");
Exit (1); } else if (piD) {exit (0);
} if ( -1 = = Setsid ()) {printf ("Setsid error\n");
Exit (1);
PID = fork ();
if (PID = = 1) {printf ("fork error\n");
Exit (1);
else if (PID) {exit (0);
} chdir ("/");
int i;
for (i = 0; i < 3; ++i) {Close (i);
} umask (0);
Return }
Note that daemons generally need to run under root permissions.
Pass
Ps-ef | grep ' Daemon '
You can see:
Root 26454 2025 0 14:20? 00:00:00./daemon
and produced a daemon.log, which is the time tag
Thu Dec 8 14:35:11 2016
Thu Dec 8 14:36:11 2016
Thu Dec 8 14:37:11 2016
Finally we want to exit the daemon, just send a sigquit signal to the daemon
Using PS again will find that the process has exited.
third, the use of Library functions Daemon () to create a daemon
In fact, we can use the daemon () function to create the daemon, its function prototype:
#include <unistd.h> int daemon (int nochdir, int noclose); DESCRIPTION the daemon () function is for programs wishing to detach themselves from the Controllin
G terminal and run in the background as System daemons. If Nochdir is zero, daemon () changes the process's current working directory to the root directory ("/");
Otherwise, the current working directory are left unchanged. If Noclose is zero, daemon () redirects standard input, standard output and standard error to/dev/null;
Otherwise, no changes are made to this file descriptors. Return VALUE (This function forks, and if the fork (2) succeeds, the parent calls _exit (2) Further errors are seen by the child only.) On Success Daemon () returns zero. If An error occurs, daemon () returns-1 and sets errno to any of the errors specified for the fork (2) and SE TSID (2).
Now let's use the daemon () function to create a daemon again, in fact, replacing our own Create_daemon () with Daemon ():
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h >
#include <fcntl.h>
#include <sys/stat.h>
#include <time.h>
#include < stdio.h>
static BOOL flag = TRUE;
void handler (int);
int main ()
{
time_t t;
int FD;
if ( -1 = = Daemon (0, 0))
{
printf ("Daemon error\n");
Exit (1);
}
struct Sigaction Act;
Act.sa_handler = handler;
Sigemptyset (&act.sa_mask);
act.sa_flags = 0;
if (Sigaction (Sigquit, &act, NULL))
{
printf ("Sigaction error.\n");
Exit (0);
}
while (flag)
{
fd = open ("/home/mick/daemon.log", O_wronly | O_creat | O_append, 0644);
if (fd = = 1)
{
printf ("Open error\n");
}
t = time (0);
Char *buf = asctime (localtime (&t));
Write (FD, buf, strlen (BUF));
Close (FD);
Sleep (a);
}
return 0;
}
void handler (int sig)
{
printf ("I got a signal%d\ni ' m quitting.\n", SIG);
Flag = false;
}
No problem, same as before.