We all know that PHP is executed by a single process. PHP's handling of multi-concurrency mainly relies on the multi-process of the server or PHP-FPM and the reuse of their processes. However, it is also significant for PHP to implement multi-process, especially in the background Cli mode. When processing large amounts of data or running the background DEMON daemon process, the advantages of multiple processes need not be said.
PHP’s multi-threading has also been mentioned, but the problem of multi-thread resource sharing and allocation within the process is difficult to solve. PHP also has an extension pthreads for multi-threading, but it is said to be unstable and requires the environment to be thread-safe, so it is not used much.
In the past, a great master in the PHP group once guided that if you want to advance in background PHP, you must avoid multi-processing. It just so happens that the daemon process in the company also uses PHP's multi-processing, combined with various materials and manuals from Gu Ge , finally understood multi-process, and wrote a small demo (implemented on a Linux system). I will summarize it in this article. If there are any mistakes or omissions, thank you for mentioning them.
To implement PHP multi-process, we need two extensions, pcntl and posix. The installation method will not be described here.
Creating a PHP subprocess is the beginning of multi-process, we need the pcntl_fork()
function;
pcntl_fork() — Spawn a fork (child process) at the current position of the current process. After this function creates a new child process, the child process will inherit the current context of the parent process and continue to execute downwards from the pcntl_fork() function like the parent process, except that the return value of pcntl_fork() obtained is different, so we The parent process and the child process can be distinguished by judging the return value, and the parent process and the child process can be assigned to do different logical processing.
When the pcntl_fork() function is successfully executed, it will return the process id (pid) of the child process in the parent process. Because the pid of the system's initial process init process is 1, the pid of the subsequent processes will be greater than this process, so we can pass Determine if the return value of pcntl_fork() is greater than 1 to confirm that the current process is the parent process;
In the child process, the return value of this function will be a fixed value of 0. We can also determine the child process by judging that the return value of pcntl_fork() is 0;
When the pcntl_fork() function fails to execute, it will return -1 in the parent process, and of course no child process will be generated.
The following is a simple example of forking a child process:
<code class="language-none"> $ppid = posix_getpid(); $pid = pcntl_fork(); if ($pid == -1) { throw new Exception('fork子进程失败!'); } elseif ($pid > 0) { cli_set_process_title("我是父进程,我的进程id是{$ppid}.");<br> sleep(30); // 保持30秒,确保能被ps查到 } else { $cpid = posix_getpid(); cli_set_process_title("我是{$ppid}的子进程,我的进程id是{$cpid}."); sleep(30); }</code>
Now let’s introduce two functions:
posix_getpid()
: Get the pid of the current process;
cli_set_process_title('响亮的名字')
: Give the current process a catchy name.
Running this example, we can see the current two PHP processes.
After the process is created, how to manage the child processes? Use signals.
In computer science, signals are a restricted method of inter-process communication in Unix, Unix-like, and other POSIX-compliant operating systems. It is an asynchronous notification mechanism used to remind the process that an event has occurred.
We manage the child process by receiving signals from the child process in the parent process and judging the status of the child process.
We need to use the pcntl_signal()
function and the pcntl_signal_dispatch()
function in the parent process to install signal handlers for each child process.
<code class="language-none">pcntl_signal (int $signo , callback $handler) 安装一个信号处理器; $signo是待处理的信号常量,callback是其处理函数 pcntl_signal_dispatch () 调用每个等待信号通过pcntl_signal()安装的处理器</code>
Common signal constants in PHP are:
<code class="language-none"> SIGCHLD 子进程退出成为僵尸进程会向父进程发送此信号 SIGHUP 进程挂起 SIGTEM 进程终止 ... // 其他请在手册中查看</code>
After installing and calling the signal processor, once the child process returns the corresponding signal to the parent process, the parent process can call the corresponding callback function to process the child process;
The methods for handling child processes are:
posix_kill()
: This function is not as the name suggests. It operates the child process by sending a signal to the child process. When necessary, you can choose to send a process termination signal to the child process to terminate the child process;
pcntl_waitpid()
: Wait for or return the child process status of fork. If the specified child process has exited when this function is called (commonly known as a zombie process), this function will return immediately and release all system resources of the child process. This The process can prevent the child process from becoming a zombie process, causing a waste of system resources;
The following are the function prototypes of the two functions:
<code class="language-none">bool posix_kill ( int $pid , int $sig ) // 向进程id为$pid的进程发送$sig信号,$sig常见信号如上; int pcntl_waitpid ( int $pid , int &$status [, int $options = 0 ] ) // 挂起当前进程的执行直到进程号为$pid的进程退出(如果$pid为-1,则等待任意一个子进程); </code>
This is the basic use of PHP multi-process. If you are interested, you can write a demo yourself and give it a try.
Finally, let me post what Brother Bird said about the advantages of PHP multi-process:
- Use multiple processes. After the child process ends, the kernel will be responsible for recycling resources
- When using multiple processes, the abnormal exit of the child process will not cause the entire process Thread to exit. The parent process will also have the opportunity to rebuild the process.
- A resident main process is only responsible for task distribution, and the logic is clearer.
By the way, there is another example, which will be uploaded to github someday. Everyone is welcome to pay attention >> Pillow Book.
Reference:
Multi-process application in PHP CLI mode - Wind and Snow Corner
Preliminary PHP multi-process programming-PureWeber - Pure Internet
Writing daemon process in php - Hu Chao's blog