TL;DR
PHP implementation daemon can be implemented through the pcntl
and posix
extensions.
Things that need to be noted in programming are:
- Let the main process leave the terminal through the second
pcntl_fork()
andposix_setsid
#Pass - pcntl_signal()
Ignore or handle
SIGHUPsignal
Multi-process programs need to pass twice - pcntl_fork()
or
pcntl_signal()Ignore the
SIGCHLDsignal to prevent the child process from becoming a Zombie process
Set the file permission mask through - umask()
to prevent inheritance of file permissions The resulting permission impact function
redirects the - STDIN/STDOUT/STDERR
of the running process to
/dev/nullor other streams
- If you start through root, change to a low-privilege user identity when running
- Timely
- chdir()
Prevent operation error paths
Consider restarting multi-process programs regularly to prevent memory leaks
In a multi-tasking computer operating system, a daemon (English: daemon, /ˈdiːmən/ or /ˈdeɪmən/) is a computer program that executes in the background. Such programs will be initialized as processes. The names of daemon programs usually end with the letter "d": for example, syslogd refers to the daemon that manages system logs.Advanced Programming in UNIX Environment (Second Edition) (hereinafter referred to as APUE) There is a cloud in Chapter 13:Usually, the daemon process does not have any existing parent process (that is, PPID=1), and is directly under init in the UNIX system process hierarchy. A daemon program usually makes itself a daemon by running fork on a child process, and then terminating its parent process immediately so that the child process can run under init. This method is often called "shelling."
The daemon process also becomes the elf process (daemon) is A process with a long life cycle. They are often started when the system boots and terminate only when the system is shut down. Because they don't have a controlling terminal, they are said to run in the background.It is noted here that daemon has the following characteristics:
- No terminal
- Running in the background
- The parent process pid is 1
ps -ax or
ps -ef, where
-x means it will be listed There is no process controlling the terminal.
pcntl extension in PHP implements the
pcntl_fork() function, which is used to fork a new process in PHP.
Session,
Process Group.
&) will also be killed after the terminal is closed, that is, the
SIGHUP issued when the control terminal is disconnected is not handled properly. signal, and the default behavior of
SIGHUP signal for a process is to exit the process.
setsid After the system call, the current process will create a new process group. If the terminal is not opened in the current process, then there will be no control terminal for this process group. There will be no problem of killing the process by closing the terminal.
posix extension in PHP implements the
posix_setsid() function, which is used to set a new process group in PHP.
The role of the second fork
First of all, the setsid
system call cannot be called by the process group leader and will return -1.
The sample code for the second fork operation is as follows:
$pid1 = pcntl_fork(); if ($pid1 > 0) { exit(0); } else if ($pid1 0) { exit(0); } else if ($pid2 <p> </p><p> Assume that we execute the application in the terminal, the process is a, and the first fork will generate a child process b. If fork succeeds, parent process a exits. b As an orphan process, it is hosted by the init process. </p><p>At this time, process b is in process group a, and process b calls <code>posix_setsid</code> to request the generation of a new process group. After the call is successful, the current process group becomes b. </p><p>At this time, process b has actually separated from any control terminal, routine: </p><pre class="brush:php;toolbar:false"><?php cli_set_process_title('process_a'); $pidA = pcntl_fork(); if ($pidA > 0) { exit(0); } else if ($pidA <p> </p><p>After executing the program: </p><pre class="brush:php;toolbar:false">➜ ~ php56 2fork1.php ➜ ~ ps ax | grep -v grep | grep -E 'process_|PID' PID TTY STAT TIME COMMAND 28203 ? Ss 0:00 process_b
Judging from the results of ps, the TTY of process_b has become ?
, that is, there is no corresponding control terminal.
When the code reaches this point, it seems that the function has been completed. process_b has not been killed after closing the terminal, but why is there a second fork operation?
An answer on StackOverflow is well written:
The second fork(2) is there to ensure that the new process is not a session leader, so it won't be able to (accidentally) allocate a controlling terminal, since daemons are not supposed to ever have a controlling terminal.
This is to prevent the actual working process from actively associating or accidentally associating with the controlling terminal, again The new process generated after fork cannot apply for an associated control terminal because it is not the leader of the process group.
To sum up, the function of secondary fork and setsid is to generate a new process group and prevent the working process from being associated with the control terminal.
SIGHUP signal handling
The default action of a process receiving the SIGHUP
signal is to end the process.
And SIGHUP
will be issued under the following circumstances:
- The control terminal is disconnected, and SIGHUP is sent to the process group leader
- Process group When the group leader exits, SIGHUP will be sent to the foreground process in the process group
- SIGHUP is often used to notify the process to reload the configuration file (mentioned in APUE, the daemon is considered unlikely to receive it because it does not have a control terminal) This is a signal, so we choose to reuse it)
Since the actual working process is not in the foreground process group, and the leader of the process group has exited and does not control the terminal, of course there will be no processing under normal circumstances. Problem, however, in order to prevent the process from exiting due to the accidental receipt of SIGHUP
, and in order to follow the conventions of daemon programming, this signal should still be processed.
Zombie process processing
What is the Zombie process
Simply speaking, the child process exits before the parent process, and the parent process does not call the wait
system call Processed, the process becomes a Zombie process.
When the child process exits before the parent process, it will send the SIGCHLD
signal to the parent process. If the parent process does not handle it, the child process will also become a Zombie process.
Zombie processes will occupy the number of processes that can be forked. Too many zombie processes will result in the inability to fork new processes.
In addition, in the Linux system, a process whose ppid is the init process will be recycled and managed by the init process after it becomes a Zombie.
Zombie process processing
From the characteristics of the Zombie process, for multi-process daemons, this problem can be solved in two ways:
- Parent process processing
SIGCHLD
Signal - Let the child process be taken over by init
No need to say more about the parent process' signal processing, just register the signal processing callback function and call the recycling method.
For the child process to be taken over by init, you can use the method of fork twice, so that the child process a from the first fork can then fork out the actual working process b, and let a exit first, so that b becomes Orphan process so that it can be hosted by the init process.
umask
umask will be inherited from the parent process, affecting the permissions to create files.
The PHP manual mentions:
umask() sets PHP's umask to mask & 0777 and returns the original umask. When PHP is used as a server module, the umask is restored after each request.
If the umask of the parent process is not set properly, unexpected effects will occur when performing some file operations:
➜ ~ cat test_umask.php <?php chdir('/tmp'); umask(0066); mkdir('test_umask', 0777); ➜ ~ php test_umask.php ➜ ~ ll /tmp | grep umask drwx--x--x 2 root root 4.0K 8月 22 17:35 test_umask
So, in order To ensure that files can be operated according to the expected permissions every time, the umask value needs to be set to 0.
Redirect 0/1/2
The 0/1/2 here refer to STDIN/STDOUT/STDERR
respectively, that is, standard input/output/error three A flow.
Sample
First let’s look at a sample:
<?php // not_redirect_std_stream_daemon.php $pid1 = pcntl_fork(); if ($pid1 > 0) { exit(0); } else if ($pid1 0) { exit(0); } else if ($pid2 <p> </p><p>The above code has almost completed all aspects mentioned at the beginning of the article, the only The difference is that the standard stream is not processed. The program can also be run in the background through the <code>php not_redirect_std_stream_daemon.php</code> directive. </p><p>在 <code>sleep</code> 的间隙,关闭终端,会发现进程退出。</p><p>通过 <code>strace</code> 观察系统调用的情况:</p><pre class="brush:php;toolbar:false">➜ ~ strace -p 6723 Process 6723 attached - interrupt to quit restart_syscall(<...>) = 0 write(1, "1503417004\n", 11) = 11 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0 nanosleep({10, 0}, 0x7fff71a30ec0) = 0 write(1, "1503417014\n", 11) = -1 EIO (Input/output error) close(2) = 0 close(1) = 0 munmap(0x7f35abf59000, 4096) = 0 close(0) = 0</...>
发现发生了 EIO 错误,导致进程退出。
原因很简单,即我们编写的 daemon 程序使用了当时启动时终端提供的标准流,当终端关闭时,标准流变得不可读不可写,一旦尝试读写,会导致进程退出。
在信海龙的博文《一个echo引起的进程崩溃》中也提到过类似的问题。
解决方案
APUE 样例
APUE 13.3中提到过一条编程规则(第6条):
某些守护进程打开
/dev/null
时期具有文件描述符0、1和2,这样,任何一个视图读标准输入、写标准输出或者标准错误的库例程都不会产生任何效果。因为守护进程并不与终端设备相关联,所以不能在终端设备上显示器输出,也无从从交互式用户那里接受输入。及时守护进程是从交互式会话启动的,但因为守护进程是在后台运行的,所以登录会话的终止并不影响守护进程。如果其他用户在同一终端设备上登录,我们也不会在该终端上见到守护进程的输出,用户也不可期望他们在终端上的输入会由守护进程读取。
简单来说:
- daemon 不应使用标准流
- 0/1/2 要设定成 /dev/null
例程中使用:
for (i = 0; i <p> </p><p>实现了这一个功能。<code>dup()</code> (参考手册)系统调用会复制输入参数中的文件描述符,并复制到最小的未分配文件描述符上。所以上述例程可以理解为:</p><pre class="brush:php;toolbar:false">关闭所有可以打开的文件描述符,包括标准输入输出错误; 打开/dev/null并赋值给变量fd0,因为标准输入已经关闭了,所以/dev/null会绑定到0,即标准输入; 因为最小未分配文件描述符为1,复制文件描述符0到文件描述符1,即标准输出也绑定到/dev/null; 因为最小未分配文件描述符为2,复制文件描述符0到文件描述符2,即标准错误也绑定到/dev/null;
开源项目实现:Workerman
Workerman 中的 Worker.php 中的 resetStd()
方法实现了类似的操作。
/** * Redirect standard input and output. * * @throws Exception */ public static function resetStd() { if (!self::$daemonize) { return; } global $STDOUT, $STDERR; $handle = fopen(self::$stdoutFile, "a"); if ($handle) { unset($handle); @fclose(STDOUT); @fclose(STDERR); $STDOUT = fopen(self::$stdoutFile, "a"); $STDERR = fopen(self::$stdoutFile, "a"); } else { throw new Exception('can not open stdoutFile ' . self::$stdoutFile); } }
Workerman 中如此实现,结合博文,可能与 PHP 的 GC 机制有关,对于 fd 0 1 2来说,PHP 会维持对这三个资源的引用计数,在直接 fclose 之后,会使得这几个 fd 对应的资源类型的变量引用计数为0,导致触发回收。所需要做的就是将这些变量变为全局变量,保证引用的存在。
推荐教程:《php教程》
The above is the detailed content of PHP implements daemon - backend. For more information, please follow other related articles on the PHP Chinese website!

The main difference between Python and JavaScript is the type system and application scenarios. 1. Python uses dynamic types, suitable for scientific computing and data analysis. 2. JavaScript adopts weak types and is widely used in front-end and full-stack development. The two have their own advantages in asynchronous programming and performance optimization, and should be decided according to project requirements when choosing.

Whether to choose Python or JavaScript depends on the project type: 1) Choose Python for data science and automation tasks; 2) Choose JavaScript for front-end and full-stack development. Python is favored for its powerful library in data processing and automation, while JavaScript is indispensable for its advantages in web interaction and full-stack development.

Python and JavaScript each have their own advantages, and the choice depends on project needs and personal preferences. 1. Python is easy to learn, with concise syntax, suitable for data science and back-end development, but has a slow execution speed. 2. JavaScript is everywhere in front-end development and has strong asynchronous programming capabilities. Node.js makes it suitable for full-stack development, but the syntax may be complex and error-prone.

JavaScriptisnotbuiltonCorC ;it'saninterpretedlanguagethatrunsonenginesoftenwritteninC .1)JavaScriptwasdesignedasalightweight,interpretedlanguageforwebbrowsers.2)EnginesevolvedfromsimpleinterpreterstoJITcompilers,typicallyinC ,improvingperformance.

JavaScript can be used for front-end and back-end development. The front-end enhances the user experience through DOM operations, and the back-end handles server tasks through Node.js. 1. Front-end example: Change the content of the web page text. 2. Backend example: Create a Node.js server.

Choosing Python or JavaScript should be based on career development, learning curve and ecosystem: 1) Career development: Python is suitable for data science and back-end development, while JavaScript is suitable for front-end and full-stack development. 2) Learning curve: Python syntax is concise and suitable for beginners; JavaScript syntax is flexible. 3) Ecosystem: Python has rich scientific computing libraries, and JavaScript has a powerful front-end framework.

The power of the JavaScript framework lies in simplifying development, improving user experience and application performance. When choosing a framework, consider: 1. Project size and complexity, 2. Team experience, 3. Ecosystem and community support.

Introduction I know you may find it strange, what exactly does JavaScript, C and browser have to do? They seem to be unrelated, but in fact, they play a very important role in modern web development. Today we will discuss the close connection between these three. Through this article, you will learn how JavaScript runs in the browser, the role of C in the browser engine, and how they work together to drive rendering and interaction of web pages. We all know the relationship between JavaScript and browser. JavaScript is the core language of front-end development. It runs directly in the browser, making web pages vivid and interesting. Have you ever wondered why JavaScr


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Safe Exam Browser
Safe Exam Browser is a secure browser environment for taking online exams securely. This software turns any computer into a secure workstation. It controls access to any utility and prevents students from using unauthorized resources.

SublimeText3 Linux new version
SublimeText3 Linux latest version

DVWA
Damn Vulnerable Web App (DVWA) is a PHP/MySQL web application that is very vulnerable. Its main goals are to be an aid for security professionals to test their skills and tools in a legal environment, to help web developers better understand the process of securing web applications, and to help teachers/students teach/learn in a classroom environment Web application security. The goal of DVWA is to practice some of the most common web vulnerabilities through a simple and straightforward interface, with varying degrees of difficulty. Please note that this software

SublimeText3 English version
Recommended: Win version, supports code prompts!

Dreamweaver Mac version
Visual web development tools
