Home > Backend Development > PHP Tutorial > Write a Daemon daemon process in PHP_PHP tutorial

Write a Daemon daemon process in PHP_PHP tutorial

WBOY
Release: 2016-07-13 10:33:04
Original
1388 people have browsed it

Daemon

This is another interesting concept. Daemon means "elf" in English, just like the ones we often see in Disney animations. Some can fly, some can't, and they often surround the protagonists of the cartoons. Wandering around, giving some advice, occasionally bumping into pillars unluckily, and sometimes coming up with some little tricks to save the protagonist from the enemy. Because of this, daemon is sometimes translated as "Guardian Saint". Therefore, the daemon process also has two translations in China. Some people translate it as "elf process" and some people translate it as "daemon process". Both of these terms appear frequently.

Similar to real daemons, daemon processes are also accustomed to hiding themselves from people's sight and silently contributing to the system. Sometimes people also call them "background service processes". The life of daemon processes is very long. Generally speaking, they will not exit from the moment they are executed until the entire system is shut down. Almost all server programs, including the well-known Apache and wu-FTP, are implemented in the form of daemon processes. For many common commands under Linux, such as inetd and ftpd, the letter d at the end refers to daemon.

Why must we use daemon process? The interface for each system in Linux to communicate with users is called a terminal. Every process that starts running from this terminal will be attached to this terminal. This terminal is called the controlling terminal (Controlling terminal) of these processes. When the controlling terminal When closed, the corresponding process will be automatically closed. Regarding this point, readers can try it with XTerm in X-Window. (Each XTerm is an open terminal.) We can start the application by typing commands, such as: $netscape Then we close the XTerm window and the netscape we just started The window will suddenly evaporate along with it. However, the daemon process can break through this limitation. Even if the corresponding terminal is closed, it can exist in the system for a long time. If we want a process to live for a long time, it will not be affected by user or terminal or other changes. If it is affected, this process must be turned into a daemon process.

Programming rules for Daemon processes

If we want to turn our process into a daemon process, we must strictly follow the following steps:

1. Call fork to generate a child process, and the parent process exits at the same time. All our subsequent work is done in the child process. To do this we can:

  • If we execute the program from the command line, this can create the illusion that the program has been executed, and the shell will go back and wait for the next command;
  • The new process just generated through fork will definitely not be the leader of a process group, which provides a prerequisite guarantee for the execution of step 2.

This will also cause a very interesting phenomenon: since the parent process has exited before the child process, the child process will have no parent process and become an orphan process (orphan). Whenever the system finds an orphan process, it will automatically be adopted by process No. 1. In this way, the original child process will become a child process of process No. 1.

2. Call setsid system call. This is the most important step in the entire process. Its function is to create a new session and serve as the session leader. If the calling process is the leader of a process group, the call will fail, but this was guaranteed in step 1. Calling setsid has three functions:

  • Let the process get rid of the control of the original session;
  • Let the process get rid of the control of the original process group;
  • Let the process get rid of the control of the original controlling terminal;

In short, it is to make the calling process completely independent and out of the control of all other processes.

3. Switch the current working directory to the root directory.

If we execute this process on a temporarily loaded file system, such as: /mnt/floppy/, the current working directory of the process will be /mnt/floppy/. The file system cannot be unmounted (umount) while the entire process is running, regardless of whether we are using this file system, which will bring us a lot of inconvenience. The solution is to use the chdir system call to change the current working directory to the root directory. No one will want to remove the root directory.

Of course, in this step, if there are special needs, we can also change the current working directory to another path, such as /tmp.

4. Set the file permission mask to 0.

This requires calling the system call umask, see Appendix 3. Each process inherits a file permission mask from the parent process. When a new file is created, this mask is used to set the default access permissions of the file and block certain permissions, such as write permissions for general users. When another process uses exec to call the daemon program we wrote, because we don't know what the file permission mask of that process is, it will cause some trouble when we create a new file. Therefore, we should reset the file permission mask. We can set it to any value we want, but generally, everyone sets it to 0, so that it will not block any user operations.

If your application does not involve creating new files or setting file access permissions at all, you can completely kick off the file permission mask and skip this step.

5. Close all unnecessary files.

Similar to the file permission mask, our new process will inherit some open files from the parent process. These opened files may never be read or written by our daemon process, but they still consume system resources and may cause the file system where they are located to be unable to be unmounted. It should be pointed out that the three files with file descriptors 0, 1 and 2 (the concept of file descriptors will be introduced in the next chapter), which are what we often call input, output and error files, also need to be closed. . It is likely that many readers will wonder about this, don't we need input and output? But the fact is that after step 2 above, our daemon process has lost contact with the control terminal it belongs to. The characters we input from the terminal cannot reach the daemon process. The daemon process uses conventional methods (such as printf) to output The characters are also impossible to display on our terminal. Therefore, these three files have lost their existence value and should be closed.

Writing a daemon

In my previous article, I introduced the use of Gearman. In my project, I use PHP to write a worker that runs all the time. If you follow the example recommended by Gearman and just wait for the task in a simple loop, there will be some problems, including: 1. After the code is modified, how to make the code modification take effect; 2. When restarting the Worker, how to ensure that the current Restart after the task processing is completed.

In response to this problem, I have considered the following solutions:

  1. After each code modification, the Worker needs to be restarted manually (kill first and then start). This only solves the problem of reloading the configuration file.
  2. Set in the Worker and restart the Worker after a single task cycle is completed. The problem with this solution is that it consumes a lot of money.
  3. Add an exit function in the Worker. If the Worker needs to exit, send an exit call with a higher priority on the client side. This requires the cooperation of the client, which is not suitable when using background tasks.
  4. Check whether the file has changed in the Worker. If it has changed, exit and restart itself.
  5. Write signal control for Worker and accept restart instructions, similar to the http restart graceful instruction.

Finally, by combining methods 4 and 5, you can implement such a Daemon. If the configuration file changes, it will automatically restart; if it receives the user's kill -1 pid signal, it will also restart.

The code is as follows:

<?php

declare( ticks = 1 );
// This case will check the config file regularly, if the config file changed, it will restart it self
// If you want to restart the daemon gracefully, give it a HUP signal
// by shiqiang<cocowool@gmail.com> at 2011-12-04

$init_md5 = md5_file( 'config.php');

// register signal handler
pcntl_signal( SIGALRM, "signal_handler", true );
pcntl_signal( SIGHUP, 'signal_handler', TRUE );

$job_flag = FALSE;    //Job status flag, to justify if the job has been finished
$signal_flag = FALSE;    //Signal status flag, to justify whether we received the kill -1 signal

while( 1 ){
    $job_flag = FALSE;    //Job status flag
    print "Worker start running ... n";
    sleep(5);
    print "Worker's task done ... n";
    $flag = TRUE;    //Job status flag
    AutoStart( $signal_flag );
}

function signal_handler( $signal ) {
    global $job_flag;
    global $signal_flag;

    switch( $signal ){
        case SIGQUIT:
            print date('y-m-d H:i:s', time() ) . " Caught Signal : SIGQUIT - No : $signal n";
            exit(0);
            break;
        case SIGSTOP:
            print date('y-m-d H:i:s', time() ) . " Caught Signal : SIGSTOP - No : $signal n";
            break;
        case SIGHUP:
            print date('y-m-d H:i:s', time() ) . " Caught Signal : SIGHUP - No : $signal n";
            if( $flag === TRUE ){
                AutoStart( TRUE );
            }else{
                $signal_flag = TRUE;
            }
            break;
        case SIGALRM:
            print date('y-m-d H:i:s', time() ) . " Caught Signal : SIGALRM - No : $signal n";
            //pcntl_exec( '/bin/ls' );
            pcntl_alarm( 5 );
            break;
        default:
            break;
    }
}

function AutoStart( $signal = FALSE, $filename = 'config.php' ){
    global $init_md5;

    if( $signal || md5_file( $filename ) != $init_md5 ){
        print "The config file has been changed, we are going to restart. n";
        $pid = pcntl_fork();
        if( $pid == -1 ){
            print "Fork error n";
        }else if( $pid > 0 ){
            print "Parent exit n";
            exit(0);
        }else{
            $init_md5 = md5_file( $filename );
            print "Child continue to run n";
        }
    }
}
?>
Copy after login

www.bkjia.comtruehttp: //www.bkjia.com/PHPjc/752556.htmlTechArticleDaemon process is another interesting concept. Daemon means "elf" in English, just like Of those we often see in Disney animations, some can fly and some can’t. Often...
Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template