C programming Linux daemon instances

  • 2020-04-02 02:57:51
  • OfStack

A Daemon is a special process that runs in the background. It is independent of the control terminal and periodically performs certain tasks or waits to process certain events that occur. Daemons are a useful progression. Most Linux servers are implemented using daemons. For example, Internet server inetd, Web server HTTPD and so on. At the same time, daemons perform many system tasks. For example, job planning process crond, printing process LPD, and so on.

Daemons programming itself is not complex, complex is the various versions of Unix implementation mechanism is not the same, resulting in different Unix environment daemons programming rules are not the same. This requires the reader to be aware that copying the rules from some books (especially BSD4.3 and lower versions of System V) to Linux can lead to errors. The following is a comprehensive introduction to the programming essentials of daemons under Linux and a detailed example.

one Daemons and their features

The most important feature of daemons is that they run in the background. At this point the DOS resident memory program TSR is similar. Second, the daemon must be isolated from its pre-run environment. These environments include open file descriptors, control terminals, session and process groups, working directories, and file creation masks. These environments are typically inherited by daemons from the parent process (especially the shell) that executes them. Finally, there is something special about the way guard starts. It can be launched from the startup script /etc/rc.d when the Linux system starts, it can be launched by the job planner crond, and it can be executed by the user terminal (usually the shell).

In short, daemons are basically indistinguishable from normal processes, except for these special features. Therefore, writing daemons is essentially transforming a normal process into a daemon based on the characteristics of the above daemons. Processes are easier to understand and program if the reader has a deeper understanding of them.

two Programming essentials for daemons

As mentioned earlier, the programming rules for daemons in different Unix environments are not consistent. Fortunately, the programming principles of daemons are the same, but the implementation details are different. This principle is to satisfy the characteristics of daemons. At the same time, Linux is SVR4 based on Syetem V and follows the Posix standard, which is more convenient to implement than BSD4. The programming essentials are as follows;

1. Run in the background.

Daemons are put into the background for execution to avoid hanging control terminals. By calling fork in the process to terminate the parent process, the Daemon executes in the background in the child process.


if(pid=fork()) exit(0);//Is the parent process, ends the parent process, the child process continues

2. Disengage from control terminal, login session and process group

It is necessary to first introduce the relationship between processes and control terminals, login sessions, and process groups in Linux: a process belongs to a process group, and the process group number (GID) is the process number (PID) of the process leader. A login session can contain multiple process groups. These process groups share a control terminal. This control terminal is usually the login terminal for the creation process.

Control terminals, login sessions, and process groups are usually inherited from the parent process. Our aim is to get rid of them and make them immune to their influence. The method is to call setsid() to make the process session leader based on point 1:
Setsid ();

Note: the setsid() call failed while the process was session leader. But the first point already guarantees that the process is not a session leader. After the successful setsid() call, the process becomes the new session leader and the new process leader, and detach from the original login session and process group. Because the session process is exclusive to the control terminal, the process is detached from the control terminal at the same time.

3. Forbid the process to reopen the control terminal

The process has now become a terminal-free session leader. But it can reapply to open a control terminal. You can prevent a process from reopening the control terminal by making it no longer the session leader:


if(pid=fork()) exit(0);//Ends the first child, and the second child continues (the second child is no longer the session leader)

4. Close the open file descriptor

The process inherits the open file descriptor from the parent process that created it. If not shut down, it wastes system resources, causes the file system where the process resides to fail to unload, and causes unexpected errors. Close them as follows:


for(i=0;i Close the open file descriptor close(i);>

5. Change the current working directory

When a process is active, the file system in which its working directory resides cannot be unloaded. You generally need to change the working directory to the root directory. For the core dump, the process writing the run log changes the working directory to a specific directory such as /tmpchdir("/")

6. Reset the file creation mask

The 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 the SIGCHLD signal

Processing the SIGCHLD signal is not required. But for some processes, especially server processes, it is common to generate child processes to handle requests when they arrive. If the parent process does not wait for the child process to finish, the child process becomes a zombie and consumes system resources. If the parent process waits for the child process to finish, it will increase the burden on the parent process and affect the concurrent performance of the server process. Under Linux, you can simply set the operation of the SIGCHLD signal to SIG_IGN.

Signal (SIGCHLD, SIG_IGN);

In this way, the kernel does not produce a zombie at the end of a child process. This is different from BSD4, where you must explicitly wait for the child process to finish before you can release the zombie process.

3. Daemon instance

The daemon instance consists of two parts: 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 one minute. The init_daemon function in the initializer is responsible for generating the daemon. Readers can generate their own daemons using the init_daemon function.

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);//Is the parent process, the end of the parent process
else if(pid< 0)
exit(1);//Fork failed, exit
//Is the first child process, the background continues to execute setsid();//The first child process becomes the new session leader and process leader
//And separate from the control terminal
if(pid=fork())
exit(0);//Is the first child process, the end of the first child process
else if(pid< 0)
exit(1);//Fork failed, exit
//Is the second child process, continue
//The second child is no longer the session leader for(i=0;i< NOFILE;++i)//Close the open file descriptor
close(i);
chdir( " /tmp " );//Change the working directory to/TMP
umask(0);//Reset the file creation mask
return;
}

2. Test. C list

#include < stdio.h >
#include < time.h > void init_daemon(void);//The daemon initializes the function main()
{
FILE *fp;
time_t t;
init_daemon();//Initialize as Daemon while(1)//Report the running status
to test.log every one minute {
sleep(60);//1 minute sleep
if((fp=fopen( " test.log " , " a " )) >=0)
{
t=time(0);
fprintf(fp, " I'm here at %sn " ,asctime(localtime(&t)) );
fclose(fp);
}
}
}

The above program in RedHat Linux6.0 compiled through. The steps are as follows:
Test init. C test. C
Execution:. / test
View the process: ps and ef
The output shows that the various features of the test daemon meet the above requirements.


Related articles: