Many services are turned on when the Linux/unix system is booted, and these services are called daemons (also called daemon processes). A daemon is a process that is detached from the control terminal and periodically performs some sort of task in the background or waits for certain events to be processed, leaving the terminal in order to prevent the process from being displayed on any terminal and the process will not be terminated by any interrupt information generated by the terminal.
General steps to create a daemon :
(1) Create child process, exit parent process
In order to disengage from the control terminal, the parent process needs to be exited, and subsequent work is done by the child process. In Linux, the parent process exits before the child process, causing the child process to become an orphan process, which is automatically adopted by the 1th process (init) when the system discovers an orphan process, so that the original child process becomes a child of the INIT process.
Ps–ef | grep procname to view a process's parent-child relationship through Pid/ppid
(2) Create a new session in a child process
Use the system function Setsid to complete.
Man 2 setsid See a description of the SETSID function
Setsid–creates a session and sets Theprocess group ID
#include <unistd.h>
pid_t setsid (void);
Setsid () creates a new session if thecalling process is not a process group leader. The calling process is Theleader of the new session, the process group leader of the new process Group,and have no controll ing TTY. The process group ID and session ID of the The callingprocess is set to the PID of the calling process. The calling process would bethe only process in this new process group and the new session.
Process Group : is a collection of one or more processes. The process group has a process group ID to uniquely identify. In addition to the process number PID, the process group ID is also a prerequisite property for a process. Each process group has a leader process whose process number equals the process group ID, and the process group ID is not affected by the exit of the leader process.
setsid function : Used to create a new session and serve as the leader of the conversation group. Call Setsid has 3 functions
(a) to get the process out of control of the original session;
(b) To get the process out of the control of the original process group;
(c) To get the process out of control of the original control terminal;
purpose of using the SETSID function : Because the first step of creating the daemon calls the fork function to create the child process and then exits the parent process. Because when the fork function is called, the child process copies the session period of the parent process, the process group, the control terminal, and so on, although the parent process exits, but the session period, the process group, the control terminal and so on have not changed, so this is not the true sense of independence opened. With the SETSID function, the process can be completely isolated from the control of other processes.
(3) Change the current directory to the root directory
A child process created with fork inherits the current working directory of the parent process. Because the file system in which the current directory is located cannot be uninstalled while the process is running, this can cause a lot of trouble for future use. Therefore, it is common practice to have the root directory "/" as the current working directory of the Daemon. In this way, the above problems can be avoided. If you have special needs, you can also change the current working directory to another path. The way to change the working directory is to use the ChDir function.
(4) Reset file permission mask
File permission mask: refers to the corresponding bit in the file permission to block out. For example, there is a file permission mask of 050, which masks the readable and executable permissions of the filegroup owner (corresponding to binary, RWX, 101). Because the child process created by the Fork function inherits the file permission mask of the parent process, this creates a lot of trouble for the child process to use the file. Therefore, setting the file permission mask to 0 (that is, not masking any permissions) can enhance the daemon's flexibility. The function that sets the file permission mask is umask. The usual method of use is Umask (0).
(5) Close file descriptor
Child processes created with fork also inherit some files that have already been opened from the parent process. These files that are opened may never be read and written by the daemon, but they consume system resources as well, and may cause the file system that resides to fail to unload. After using the SETSID call, the daemon has lost contact with the owning control terminal, so the characters entered from the terminal are not likely to reach the daemon, and the characters that are output by a regular method (such as printf) in the daemon cannot be displayed on the terminal. Therefore, three files with a file descriptor of 0, 1, 2 (that is, standard input, standard output, standard error output) have lost their existing value and should be closed.
(6) Daemon exit process
When a user needs an external stop daemon, the KILL command is typically used to stop the daemon. Therefore, the daemon needs to encode to achieve the signal signal processing of kill, to achieve a normal exit process.
The following is a simple implementation:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h>//open #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <sys/wait.h> #include < Signal.h> #define Maxfile 65535 volatile sig_atomic_t _running = 1; int FD; Signal handler void Sigterm_handler (int arg) {_running = 0; } int main () {pid_t pid; Char *buf = "This is a Daemon, wcdj\n"; /* Block some signals about control terminal operation * To prevent the daemon from operating properly when the control terminal is disturbed to exit or hang * */Signal (SIGINT, sig_ign);//terminal interrupt signal (sigh Up, sig_ign);//connection hangs signal (sigquit, sig_ign);//terminal exits signal (sigpipe, sig_ign);//writes data to the non-read process pipeline signal (SIGTT OU, sig_ign);//Background program try write operation Signal (Sigttin, sig_ign);//Background program try to read operation signal (SIGTERM, sig_ign);//termination//test Sleep ();//try cmd:./test &; Kill-s SIGTERM pid//[1] fork child process and exit father process PID = fork (); if (PID < 0) {perror ("fork error!"); Exit (1); } else if (PID > 0) {exit (0); }//[2] Create a new session setsid (); [3] Set current path char szpath[1024]; if (GETCWD (szpath, sizeof (szpath)) = = NULL) {perror ("getcwd"); Exit (1); } else {chdir (szpath); printf ("Set Current path SUCC [%s]\n", szpath); }//[4] umask 0 umask (0); [5] Close useless fd int i; for (i = 0; i < maxfile; ++i) for (i = 3; i < Maxfile; ++i) {Close (i); }//[6] Set TERMIANL signal signal (SIGTERM, Sigterm_handler); Open file and set RW limit if (FD = open ("outfile", o_creat| o_wronly| O_append, 0600)) < 0) {perror ("open"); Exit (1); } printf ("\ndaemon begin to work ..., and use kill-9 PID to terminate\n"); Do sth in Loop while (_running) {if (write (FD, buf, strlen (BUF))! = strlen (buf)) {perror ("write"); Close (FD); Exit (1); } usleep (1000*1000);//1 S} close (FD); Print data if (FD = open ("outfile", O_rdonly) < 0) {perror ("open"); Exit (1); } char szbuf[1024] = {0}; if (read (FD, szbuf, sizeof (szbuf)) = =-1) {perror ("read"); Exit (1); } printf ("Read 1024x768 bytes:\n%s\n", szbuf); Close (FD); return 0; }/* gcc-wall-g-o test test.c PS UX | Grep-v grep | grep test tail-f outfile kill-s SIGTERM PID */
Reference:
[1] Daemon
[2] Writing the Linux/unix daemon
[3] Linux signal signal processing function
[4] The usage of sig_atomic_t in Linux signal mask function
Implementation of the next simple daemon for Linux (Daemon)