1. Daemon Overview
Linux Daemon is a special process running in the background. It is independent of the control terminal and periodically executes a task or waits to process some events. It can run without user input and provide certain services, either for the entire system or a user program. Most servers in Linux are implemented through the daemon process. Common daemon processes include syslogd, httpd, sendmail, and mysqld.
The daemon generally starts running when the system is started. Unless it is forcibly terminated, it remains running until the system is shut down. Daemon often run with root privileges because they use special ports (1-1024) or access certain special resources.
The parent process of a daemon is the init process, because its real parent process exits before the child process exits after fork leaves the child process, therefore, it is an orphan process inherited by init. The daemon process is a non-interactive program with no control terminal. Therefore, any output from stdout to the standard output device or stderr to the standard error device requires special processing.
The daemon name usually ends with d, such as sshd, xinetd, and crond.
Step 2: Create a daemon
First, we need to understand some basic concepts:
Process Group:
- Each process also belongs to a process group.
- Each process master has a process group number, which is equal to the PID Number of the process group leader.
- A process can only set the process group ID for itself or its sub-process
Session Period:
A session is a collection of one or more Process Groups.
The setsid () function creates a dialog period:
If the process that calls setsid is not the leader of a process group, this function creates a new session.
(1) This process becomes the first process in the dialog period.
(2) The process becomes the leader process of a new process group.
(3) The process has no control terminal. If the process has a control terminal before calling setsid, the contact with the terminal is removed. If the process is the leader of a process group, this function returns an error.
(4) To ensure this, we first call fork () and then exit (). At this time, only the sub-process is running.
Here are the steps required to create a daemon:
The general steps for writing a daemon are as follows:
(1) execute fork in the parent process and exit the launch;
(2) Call the setsid function in the sub-process to create a new session;
(3) Call the chdir function in the sub-process to make the root directory "/" The working directory of the sub-process;
(4) Call the umask function in the sub-process and set the umask of the process to 0;
(5) disable unnecessary file descriptors in sub-Processes
Note:
1. Run in the background.
To avoid pending the control terminal, place the Daemon in the background for execution. The method is to call fork in the process to terminate the parent process and run Daemon in the background of the child process.
If (pid = fork ())
Exit (0); // indicates the parent process. The parent process ends and the child process continues.
2. log on to the session and process group from the control terminal.
It is necessary to first introduce the relationship between processes and control terminals, logon sessions, and process groups in Linux: Processes belong to a process group, process group number (GID) is the process ID (PID) of the process leader ). A logon session can contain multiple Process Groups. These process groups share a control terminal. This control terminal is usually the login terminal that creates a process.
Control terminal, logon sessions and process groups are generally inherited from the parent process. Our goal is to get rid of them so that they are not affected. The method is to call setsid () on the basis of to make the process a session leader:
Setsid ();
Note: setsid () fails to be called when the process is a session leader. However, the first point is that the process is not the session leader. After the setsid () call is successful, the process becomes a new session leader and a new process leader, and is detached from the original logon session and process group. Because the session process is dedicated to the control terminal, the process is separated from the control terminal at the same time.
3. Prohibit the process from re-opening the control terminal
Now, the process has become the no-end session leader. But it can re-apply to open a control terminal. You can disable the process from re-opening the control terminal by making the process no longer the session leader:
If (pid = fork ())
Exit (0); // end the first child process and the second child process (the second child process is no longer the session leader)
4. Disable open file descriptors
A process inherits the opened file descriptor from the parent process that created it. If you do not close it, system resources will be wasted, and the file system where the process is located will not be able to be detached and unexpected errors will occur. Close them as follows:
For (I = 0; I close the opened file descriptor close (I);>
5. Change the current working directory
When a process is active, the file system of its working directory cannot be detached. Generally, you need to change the working directory to the root directory. For processes that need to dump the core, write the running log to change the working directory to a specific directory, such as/tmpchdir ("/")
6. Reset the file to create a mask
A process inherits the file creation mask from the parent process that created it. It may modify the access bit of the file created by the daemon. To prevent this, clear the file creation mask: umask (0 );
7. Process SIGCHLD Signal
It is not necessary to process SIGCHLD signals. However, some processes, especially server processes, usually generate sub-processes to process requests when requests arrive. If the parent process does not wait for the child process to end, the child process will become a zombie process, occupying system resources. If the parent process waits for the child process to end, it will increase the burden on the parent process and affect the concurrent performance of the server process. In Linux, you can set the SIGCHLD signal operation to SIG_IGN.
Signal (SIGCHLD, SIG_IGN );
In this way, the kernel will not generate zombie processes when the child process ends. This is different from BSD4. In BSD4, you must explicitly wait for the child process to end before releasing the zombie process.
3. Create a daemon
Before creating an instance, we need to know how to use setsid:
# Include <unistd. h>
Pid_t setsid (void );
DESCRIPTION
Setsid () creates a new session if the calling process is not a process
Group leader. The calling process is the leader of the new session,
The process group leader of the new process group, 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 will be
The only process in this new process group and in this new session.
// The invocation process must be a non-current process group leader. After the call, a new session period is generated, and there is only one process group in the session period, and the invocation process group is long, no control terminal. The newly generated group ID and session ID are set to the PID of the calling process.
RETURN VALUE
On success, the (new) session ID of the calling process is returned.
On error, (pid_t)-1 is returned, and errno is set to indicate
Error.
Create a daemon according to the preceding steps:
The following program creates a daemon and writes the current time to the daemon. log file every minute using this daemon. log.
#include <stdio.h><unistd.h><stdlib.h><time.h><fcntl.h><.h><sys/stat.h> ERR_EXIT(m) \ ( creat_daemon( main((= open(,O_WRONLY|O_CREAT|O_APPEND,(fd == -= time( *buf = asctime(localtime(& creat_daemon(=( pid == -(pid > (setsid() == -( i = ; i < ; ++
Result:
<Unistd. h> <stdlib. h> <time. h> <fcntl. h> <. h> <sys/stat. h> ERR_EXIT (m) \ (creat_daemon (main (daemon (,) =-(= open (, O_WRONLY | O_CREAT | O_APPEND, (fd =-= time (* buf = asctime (localtime (&
When daemon (0, 0:
<Unistd. h> <stdlib. h> <time. h> <fcntl. h> <. h> <sys/stat. h> ERR_EXIT (m) \ (creat_daemon (nochdir, main (, (= open (, O_WRONLY | O_CREAT | O_APPEND, (fd =-= time (* buf = asctime (localtime (& creat_daemon (nochdir, = (pid =-(pid> (setsid () =-(nochdir = (noclose = (I =; I <; ++