In Linux, to program a daemon, follow these steps. 1. Make the INIT process the parent process of the newly generated process.After the fork function is called to create a sub-process, the parent process immediately exits. In this way, the child process will become an orphan process and be taken over by the INIT process. At the same time, the new process will become running in the background. 2. Call the setsid FunctionCall the setsid function to remove the newly created process from the control terminal. At the same time, a new process group is created and becomes the first process of the Process Group. To better understand this step, the following describes the basic concepts of process groups and sessions. In Linux, all processes belong to their respective Process Groups. A process group is a collection of one or more processes. For example, a class is considered a process group, and its members are processes. A class must have at least one member. When the last member of a class does not exist, the class does not exist, that is, the Process Group disappears. Each process group has a process ID similar to the process ID. The process group ID is determined by the process ID of the lead process. Each process group has a lead process. The existence of a process group is irrelevant to that of the lead process. A session is a collection of one or more Process Groups. Similar to a process group, each session has a lead process. Linux is a multi-user operating system with multiple processes belonging to different users at the same time. If a user sends a signal on a terminal, such as pressing CTRL + C to send a SIGINT signal, how can he ensure that the signal is correctly sent to the corresponding process, does it affect the processes of users using other terminals? Session and process group are the methods used by the Linux kernel to manage user processes in the case of multiple users. Each process belongs to a process group, and the process group belongs to a session. When a user logs on to the system from a terminal (whether a terminal or a Pseudo Terminal), the system creates a new session. Processes started on the terminal will be assigned to the Process Group of the session by the system. The process in the session is connected to a terminal through the lead process (often called the control process) in the session. This is the session control terminal. A session can only have one control terminal. If a session has a control terminal, it must have a foreground process group. Processes in this group can obtain input from the control terminal. At this time, all other process groups are background process groups. Figure 8.3 shows the relationships between sessions, Process Groups, processes, and control terminals. Figure 8.3 relationship between sessions, Process Groups, processes and control terminals Because the daemon does not have a control terminal, and the child process created using the fork function inherits the control terminal, session, and process group of the parent process, a new session must be created, to remove the influence of the parent process. The setsid function is provided in Linux to create a new session. Information about the setsid function is shown in table 8.1. Table 8.1 setsid Functions
Header file |
<Unistd. h> |
Function Form |
Pid_t setsid (void ); |
Return Value |
Successful |
Failed |
Whether to set errno |
Session ID of the calling Process |
−1 |
Yes |
The setsid function creates a new session and makes the process that calls the setsid function the lead process of the new session. The process that calls the setsid function is the only process group in the newly created session. The process group ID is the process number of the called process. The setsid function generates this result with a condition that the calling process is not the leading process of a process. Because the fork parent process is called in step 1 to exit, the child process cannot be the lead process of the process group. The lead process of the session has no control terminal connected to it. At this point, the requirement that the daemon process does not have a control terminal is met. 3. Change the current working directoryThe child process generated by using the fork function inherits the current working directory of the parent process. When a process does not end, its working directory cannot be uninstalled. To prevent this problem, the daemon usually changes its working directory to the root directory (/directory ). The function used to change the working directory is chdir. 4. disable file descriptors and redirect standard input, output, and error outputNew processes inherit some opened file descriptors from the parent process. If these file descriptors are not used, disable them. The daemon is running on the system background and should not have any output information on the terminal. You can use the DUP function to redirect standard input, output, and error output to A/dev/null device (/dev/null is an empty device and no output is written to it ). The code below is as follows: ... Int FD; // Redirect the standard input/output to an empty Device FD = open ("/dev/null", o_rdwr, 0 ); If (FD! =-1) { Dup2 (FD, stdin_fileno ); Dup2 (FD, stdout_fileno ); Dup2 (FD, stderr_fileno ); If (FD> 2) Close (FD ); } ... 5. Set the File Permission creation mask for the daemon.In many cases, the daemon creates some temporary files. For the sake of security, users often do not want these files to be viewed by other users. In this case, you can use the umask function to modify file permissions and create mask values to meet the requirements of the daemon. 8.2.2 daemon implementationThis section describes an instance created by a daemon. The daemon function is defined in program p8.1.c to create the daemon process. Its creation idea is described in detail in 8.2.1. The specific code of the program is as follows: // P8.1.c daemon implementation # Include <stdio. h> # Include <unistd. h> # Include <sys/types. h> # Include <sys/STAT. h> # Include <fcntl. h> /* The Daemon function is used to convert the process that calls the function to the daemon process */ Int Daemon (INT nochdir, int noclose) { Pid_t PID; PID = fork (); /* If the process fails to be created */ If (PID <0) { Perror ("fork "); Return-1; } /* The parent process exits */ If (PID! = 0) Exit (0 ); /* Become a session leader */ PID = setsid (); If (PID <-1) { Perror ("setsid "); Return-1; } /* Change the working directory to the root directory */ If (! Nochdir) Chdir ("/"); /* Redirect the standard input/output to an empty device */ If (! Noclose) { Int FD; FD = open ("/dev/null", o_rdwr, 0 ); If (FD! =-1) { Dup2 (FD, stdin_fileno ); Dup2 (FD, stdout_fileno ); Dup2 (FD, stderr_fileno ); If (FD> 2) Close (FD ); } } Umask (0027 ); Return 0; } Int main (void) { Daemon (0, 0 ); Sleep (1000 ); Return 0; } Use GCC to compile p8.1.c and obtain the executable file p8.1. Run this program. The program runs in the daemon process status, as shown in Figure 8.4. Figure 8.4 daemon implementation |