How to write the php Daemon and daemon_PHP Daemon

Source: Internet
Author: User
How to write the php Daemon and daemon Daemon. The Daemon daemon is a special process running in the background. It is independent of the control terminal and periodically executes a certain task. how to write the php Daemon and daemon Daemon?

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 very useful process. Php can also implement the daemon function.
I. Basic concepts
Process:Each process has a parent process. The child process exits and the parent process can be exited.
Process Group:Each process belongs to a process Group, and each process Group has a process group number, which is equal to the PID of the process group leader.
II. key points of Daemon programming
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 = pcntl_fork () exit (0); // It is the parent process. the parent process ends 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 logon 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 become the session leader: posix_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 prevent the process from re-opening the control terminal by making the process no longer the session leader: if ($ pid = pcntl_fork () exit (0); // end the first sub-process, the second sub-process continues (the second sub-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:
Fclose (STDIN), fclose (STDOUT), and fclose (STDERR) disable standard input output and error display.
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 chdir ("/")
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 process, occupying system resources. If the parent process waits for the child process to end, it will increase the burden on the parent process, affecting 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. For signal problems, refer to the Linux signal description list
III. instances

<? Php * background script control class */class DaemonCommand {private $ info_dir = "/tmp"; private $ pid_file = ""; private $ terminate = false; // whether to interrupt private $ workers_count = 0; private $ gc_enabled = null; private $ workers_max = 8; // run a maximum of eight processes public function _ construct ($ is_sington = false, $ user = 'nobody', $ output = "/dev/null") {$ this-> is_sington = $ is_sington; // whether to run a single instance, the Singleton operation creates a unique PID $ this-> user = $ user under the tmp directory; // sets the running user's default nobody $ this-> ou Tput = $ output; // Set the output location $ this-> checkPcntl ();} // check whether the environment supports pcntl and public function checkPcntl () {if (! Function_exists ('pcntl _ signal_dispatch ') {// PHP <5.3 uses ticks to handle signals instead of signature // call sighandler only every 10 ticks declare (ticks = 10 );} // Make sure PHP has support for pcntl if (! Function_exists ('pcntl _ signal ') {$ message = 'php does not appear to be compiled with the pcntl extension. this is neccesary for daemonization '; $ this-> _ log ($ message); throw new Exception ($ message) ;}// pcntl_signal (SIGTERM, array (_ CLASS __, "signalHandler"), false); pcntl_signal (SIGINT, array (_ CLASS __, "signalHandler"), false); pcntl_signal (SIGQUIT, array (_ CLASS __, "signalHandler"), false ); // Enable PHP 5.3 garbage collection if (function_exists ('gc _ enabled') {gc_enable (); $ this-> gc_enabled = gc_enabled ();}} // daemon program public function daemonize () {global $ stdin, $ stdout, $ stderr; global $ argv; set_time_limit (0 ); // only run if (php_sapi_name () under cli ()! = "Cli") {die ("only run in command line mode \ n");} // only a single instance can run if ($ this-> is_sington = true) {$ this-> pid_file = $ this-> info_dir. "/". _ CLASS __. "_". substr (basename ($ argv [0]), 0,-4 ). ". pid "; $ this-> checkPidfile ();} umask (0); // clear the file mask 0 if (pcntl_fork ()! = 0) {// is the parent process. the parent process exits exit ();} posix_setsid (); // sets the new session leader and leaves the terminal if (pcntl_fork ()! = 0) {// is the first sub-process and ends the first sub-process exit ();} chdir ("/"); // change the working directory $ this-> setUser ($ this-> user) or die ("cannot change owner"); // Close the opened file descriptor fclose (STDIN ); fclose (STDOUT); fclose (STDERR); $ stdin = fopen ($ this-> output, 'r'); $ stdout = fopen ($ this-> output, 'A'); $ stderr = fopen ($ this-> output, 'A'); if ($ this-> is_sington = true) {$ this-> createPidfile () ;}// -- check whether the pid has the public function checkPidfile () {if (! File_exists ($ this-> pid_file) {return true;} $ pid = file_get_contents ($ this-> pid_file); $ pid = intval ($ pid ); if ($ pid> 0 & posix_kill ($ pid, 0) {$ this-> _ log ("the daemon process is already started ");} else {$ this-> _ log ("the daemon proces end abnormally, please check pidfile ". $ this-> pid_file);} exit (1);} // ---- create pid public function createPidfile () {if (! Is_dir ($ this-> info_dir) {mkdir ($ this-> info_dir);} $ fp = fopen ($ this-> pid_file, 'w ') or die ("cannot create pid file"); fwrite ($ fp, posix_getpid (); fclose ($ fp); $ this-> _ log ("create pid file ". $ this-> pid_file);} // set the public function setUser ($ name) {$ result = false; if (empty ($ name) {return true ;} $ user = posix_getpwnam ($ name); if ($ user) {$ uid = $ user ['uid']; $ gid = $ user ['gid']; $ result = Posix_setuid ($ uid); posix_setgid ($ gid);} return $ result;} // signal processing function public function signalHandler ($ signo) {switch ($ signo) {// user-defined signal case SIGUSR1: // busy if ($ this-> workers_count <$ this-> workers_max) {$ pid = pcntl_fork (); if ($ pid> 0) {$ this-> workers_count ++ ;}} break; // case SIGCHLD: while ($ pid = pcntl_waitpid (-1, $ status, WNOHANG)> 0) {$ this-> workers_count --;} break; // interrupt process ca Se SIGTERM: case SIGHUP: case SIGQUIT: $ this-> terminate = true; break; default: return false ;}} /*** start process ** $ count number of processes to be started */public function start ($ count = 1) {$ this-> _ log ("daemon process is running now"); pcntl_signal (SIGCHLD, array (_ CLASS __, "signalHandler"), false ); // if worker die, minus children num while (true) {if (function_exists ('pcntl _ signal_dispatch ') {pcntl_signal_dispatch ();} I F ($ this-> terminate) {break;} $ pid =-1; if ($ this-> workers_count <$ count) {$ pid = pcntl_fork ();} if ($ pid> 0) {$ this-> workers_count ++;} elseif ($ pid = 0) {// This symbol indicates the default pcntl_signal (SIGTERM, SIG_DFL); pcntl_signal (SIGCHLD, SIG_DFL); if (! Empty ($ this-> jobs) {while ($ this-> jobs ['runtime']) {if (empty ($ this-> jobs ['argv']) {call_user_func ($ this-> jobs ['function'], $ this-> jobs ['argv']);} else {call_user_func ($ this-> jobs ['function']);} $ this-> jobs ['runtime'] --; sleep (2);} exit ();} return;} else {sleep (2) ;}$ this-> mainQuit (); exit (0) ;}// the whole process exits the public function mainQuit () {if (file_exists ($ this-> pid_file) {unlink ($ this-> pid_file); $ t His-> _ log ("delete pid file ". $ this-> pid_file);} $ this-> _ log ("daemon process exit now"); posix_kill (0, SIGKILL); exit (0 );} // add a work instance. Currently, only public function setJobs ($ jobs = array () {if (! Isset ($ jobs ['argv']) | empty ($ jobs ['argv']) {$ jobs ['argv'] = "";} if (! Isset ($ jobs ['runtime']) | empty ($ jobs ['runtime']) {$ jobs ['runtime'] = 1;} if (! Isset ($ jobs ['function']) | empty ($ jobs ['function']) {$ this-> log ("you must add a running function! ") ;}$ This-> jobs = $ jobs;} // log processing private function _ log ($ message) {printf ("% s \ t % d \ t % s \ n", date ("c"), posix_getpid (), posix_getppid (), $ message) ;}// call method 1 $ daemon = new DaemonCommand (true); $ daemon-> daemonize (); $ daemon-> start (2 ); // enable two sub-processes to work (); // call method 2 $ daemon = new DaemonCommand (true); $ daemon-> daemonize (); $ daemon-> addJobs (array ('function' => 'work', 'argv' => '', 'runtime' => 1000); // function to run The row function, the parameters of the argv running function, and the number of runtime runs $ daemon-> start (2); // enable two sub-processes to work // function work () {echo "test 1" ;}?>

The above is an introduction to the php daemon process. I hope it will be helpful for your learning.

Articles you may be interested in:
  • The php daemon and linux command nohup are used to execute the task once per second.
  • Overview of PHP program-level Daemon implementation and optimization
  • PHP implementation of multi-process parallel operations (can be used as a daemon process)
  • Share a shell script as a daemon instance that prevents PHP scripts from being suspended
  • PHP advanced programming example: write a daemon
  • PHP daemon instance
  • PHP uses a process as a daemon
  • PHP extension implementation daemon
  • Share The PHP daemon class

Daemon is a special process running in the background. It is independent of the control terminal and periodically executes a certain task...

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.