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. Daemon is a useful process. Most Linux servers are implemented using daemon. For example, the Internet server inetd and the Web Server httpd. At the same time, the daemon completes many system tasks. For example, job planning process crond and printing process LPD.
The programming of daemon is not complex. The complicated problem is that different versions of UNIX have different implementation mechanisms, resulting in inconsistent programming rules of daemon in different UNIX environments. It should be noted that copying the rules in some books (especially bsd4.3 and earlier versions of System V) will cause errors to Linux. The following describes the programming points and detailed examples of the daemon in Linux.
1. daemon process and Its Features
The most important feature of a daemon is that it runs in the background. At this point, the TSR of the resident memory program under DOS is similar. Second, the daemon must be isolated from the environment before running. These environments include unclosed file descriptors, control terminals, sessions and process groups, working directories, and file creation masks. These environments are generally inherited by the daemon from the parent process (especially the shell) that executes the daemon. Finally, the daemon startup method has its own special features. It can be started from the startup script/etc/rc. d when the Linux system is started. It can be started by the job planning process crond and executed by the user terminal (usually shell.
In short, apart from these special features, the daemon process is basically no different from the common process. Therefore, writing a daemon actually transforms a common process into a daemon according to the features of the preceding daemon. If you have a deep understanding of the process, it is easier to understand and program.
II. Key Points of daemon Programming
As mentioned above, the programming rules of daemon in different UNIX environments are inconsistent. Fortunately, the programming principles of the daemon process are the same. The difference is that the specific implementation details are different. This principle is to satisfy the characteristics of the daemon process. At the same time, Linux is a svr4 Based on syetem V and complies with the POSIX standard, which is easier to implement than bsd4. The main points of programming are as follows;
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); // It is the parent process, ends the parent process, 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 and thus occupy 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.
Iii. Daemon instance
The daemon instance consists of the main program test. C and the initialization program init. C. The main program reports the running status to the log test. log in the/tmp directory every minute. The init_daemon function in the initialization program is responsible for generating the daemon process. You can use the init_daemon function to generate your own daemon process.
1. init. c LIST
# Include <unistd. h> # include <signal. h> # include <sys/Param. h> # include <sys/types. h> # include <sys/STAT. h> void init_daemon (void) {int PID; int I; If (pid = fork () Exit (0); // It is the parent process, stop the parent process else if (PID <0) Exit (1); // fork failed, exit // is the first sub-process, and the background continues to execute setsid (); // The first sub-process becomes the new session leader and process leader // and is separated from the control terminal if (pid = fork () Exit (0); // is the first sub-process, end the first sub-process else
If (PID <0) Exit (1); // fork failed, exit // is the second sub-process, continue // the second sub-process is no longer the session leader for (I = 0; I <nofile; ++ I) // close the opened file descriptor close (I); chdir ("/tmp"); // change the working directory to/tmpumask (0 ); // reset the file creation mask return ;}
2. Test. c LIST
# Include <stdio. h> # include <time. h> void init_daemon (void); // daemon initialization function main () {file * FP; time_t t; init_daemon (); // initialize to daemonwhile (1) // test every minute. log reports the running status {sleep (60); // If (FP = fopen ("test. log "," A ")> = 0) {T = time (0); fprintf (FP," Im here at % Sn ", asctime (localtime (& T ))
); Fclose (FP );}}}
The above program is compiled in RedHat linux6.0. The procedure is as follows:
Compile: gcc-g-o Test init. C test. c
Run:./test
View process: PS-ef
From the output, we can find that the various features of the test daemon meet the above requirements.
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. Daemon is a useful process. Most Linux servers are implemented using daemon. For example, the Internet server inetd and the Web Server httpd. At the same time, the daemon completes many system tasks. For example, job planning process crond and printing process LPD.
The programming of daemon is not complex. The complicated problem is that different versions of UNIX have different implementation mechanisms, resulting in inconsistent programming rules of daemon in different UNIX environments. It should be noted that copying the rules in some books (especially bsd4.3 and earlier versions of System V) will cause errors to Linux. The following describes the programming points and detailed examples of the daemon in Linux.
1. daemon process and Its Features
The most important feature of a daemon is that it runs in the background. At this point, the TSR of the resident memory program under DOS is similar. Second, the daemon must be isolated from the environment before running. These environments include unclosed file descriptors, control terminals, sessions and process groups, working directories, and file creation masks. These environments are generally inherited by the daemon from the parent process (especially the shell) that executes the daemon. Finally, the daemon startup method has its own special features. It can be started from the startup script/etc/rc. d when the Linux system is started. It can be started by the job planning process crond and executed by the user terminal (usually shell.
In short, apart from these special features, the daemon process is basically no different from the common process. Therefore, writing a daemon actually transforms a common process into a daemon according to the features of the preceding daemon. If you have a deep understanding of the process, it is easier to understand and program.
II. Key Points of daemon Programming
As mentioned above, the programming rules of daemon in different UNIX environments are inconsistent. Fortunately, the programming principles of the daemon process are the same. The difference is that the specific implementation details are different. This principle is to satisfy the characteristics of the daemon process. At the same time, Linux is a svr4 Based on syetem V and complies with the POSIX standard, which is easier to implement than bsd4. The main points of programming are as follows;
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); // It is the parent process, ends the parent process, 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 and thus occupy 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.
Iii. Daemon instance
The daemon instance consists of the main program test. C and the initialization program init. C. The main program reports the running status to the log test. log in the/tmp directory every minute. The init_daemon function in the initialization program is responsible for generating the daemon process. You can use the init_daemon function to generate your own daemon process.
1. init. c LIST
# Include <unistd. h> # include <signal. h> # include <sys/Param. h> # include <sys/types. h> # include <sys/STAT. h> void init_daemon (void) {int PID; int I; If (pid = fork () Exit (0); // It is the parent process, stop the parent process else if (PID <0) Exit (1); // fork failed, exit // is the first sub-process, and the background continues to execute setsid (); // The first sub-process becomes the new session leader and process leader // and is separated from the control terminal if (pid = fork () Exit (0); // is the first sub-process, end the first sub-process else
If (PID <0) Exit (1); // fork failed, exit // is the second sub-process, continue // the second sub-process is no longer the session leader for (I = 0; I <nofile; ++ I) // close the opened file descriptor close (I); chdir ("/tmp"); // change the working directory to/tmpumask (0 ); // reset the file creation mask return ;}
2. Test. c LIST
# Include <stdio. h> # include <time. h> void init_daemon (void); // daemon initialization function main () {file * FP; time_t t; init_daemon (); // initialize to daemonwhile (1) // test every minute. log reports the running status {sleep (60); // If (FP = fopen ("test. log "," A ")> = 0) {T = time (0); fprintf (FP," Im here at % Sn ", asctime (localtime (& T ))
); Fclose (FP );}}}
The above program is compiled in RedHat linux6.0. The procedure is as follows:
Compile: gcc-g-o Test init. C test. c
Run:./test
View process: PS-ef
From the output, we can find that the various features of the test daemon meet the above requirements.