Transferred from: https://www.pureweber.com/article/php-multi-process-programming-preview/
Envy Naruto Naruto's shadow? Yes, the PHP program is able to activate the shadow! Want to complete the task, and feel that a process is too slow, then try a multi-process to do it. This article will cover the basic needs of PHP multi-process, how to create multi-process and basic signal control, and temporarily will not tell you how to communicate between the process and information sharing.
1. Preparation
Before you start, make sure you're not using the m$ Windows platform (because I don't have windows). Linux/bsd/unix should be no problem at all. Make sure the working environment comes up and see if we have all the PHP modules we need. Open terminal and enter the following command:
$ php-m
This command checks and prints all open extensions for the current PHP, and looks at pcntl
and posix
is in the output list.
1.1. Pcntl
If it is not found pcntl
, probably is compiled without compiling the extension. If you are the same as me to compile the installation of PHP, then you need to recompile the installation of PHP. Remember to add parameters when configuring --enable-pcntl
.
$ cd/path/to/php_source_code_dir $./configure [some other options]--enable-pcntl$ make && make install
1.2. POSIX
The goods are usually installed by default, as long as you do not add when compiling --disable-posix
.
2. Pre-knowledge
Before you continue, you need to know a little bit about Linux multi-processes. What happened to the multi-process? This is a little bit different from Naruto's avatar. First of all, Naruto grew up to large, such as 16-year-old, cough. One day he started his shadow, and he separated 5 of him. Obviously, these are the 16-year-old Naruto, not the newborn baby who will cry without knowing what to do (it's called cloning). Then, the different places come: they become independent people to do their own things, and no longer know what other fen and the original did what (of course, not like the animation in the same accumulation of experience to the original body). Unless they communicate with each other, the only thing that is before the age of 16 is their shared memory.
A classmate said, boss, you don't hang Dad? I didn't see the ninja! Well, you can go and see it again.
Finally, the preparation of knowledge is finished, is a general understanding of the main process to open the child process is what. The code of the child process is exactly the same as the main process, and there is a part of everything that is executed until the shadow is launched. See the operating system course for details.
3. The technique of Shadow
So how can you understand the contents of the scrolls without a bit of basic knowledge? Opening the reel first saw a word: fork.
3.1. Fork
Fork? Forks are forked, one is different! That's almost what it means. Create a child process with this command. Functions need to be used here pcntl_fork()
. (You can simply take a look at the PHP manual for an introduction to this function.) ) to create a PHP script:
$pid=Pcntl_fork();Once the call succeeds, things get a little different.If ( $pid == -1) { die ( ' fork failed ' ;} else if ( $pid Span class= "token operator" >== 0) {} else {} /span>
pcntl_fork()
function to create a child process, the only difference between a child process and a parent process is that the PID (process ID) and PPID (parent process ID) are different. Under Terminal view process with ps
command (ask man to see how PS is used: man ps
). When the function returns a value of-1, the fork fails. Try if
Adding a sentence in front: echo $pid . PHP_EOL;
. Running your script, the output might look like this (the code for the child process and the parent process is the same):
67789 # This is the 0 that the parent process prints # This is the child process printing
pcntl_fork()
After the function call succeeds, the PID of the child process is returned in the parent process, and 0 is returned in the child process. So, the following directly with if
the branch to control the parent process and the child process do different things.
3.2. Assigning tasks
Then let's talk about Naruto's 16-year-old avatar, assigning two simple output tasks to the original and the Avatar:
$parentPid=Getmypid();This is the legendary memory before the age of 16.$pid=Pcntl_fork();Once the call succeeds, things get a little different.If($pid==-1){Die(' Fork failed ');}ElseIf($pid==0){$mypid=Getmypid();Get the PID of the current process with the Getmypid () functionEcho' I am child process. My PID is '.$mypid ' and my father ' s pid is ' Span class= "token variable" > $parentPid php_eol;} else {echo ' Oh my god! I am a Father now! My Child's pid is $pid. ' and mine is ' $parentPid php_eol;}
The result of the output might be this:
Oh my god! I am a Father now! My Child's PID is 68066 and mine are 68065I am child process. My PID is 68066 and my father ' s PID is 68065
Again, after the pcntl_fork()
call succeeds, a program becomes two programs: a program gets a $pid
variable value of 0, it is a child process, another program gets a $pid
value greater than 0, this value is the PID of the child process, it is the parent process. In the following branch statement, $pid
different code is run because of different values. Again, the code for the child process is the same as the parent process. So it is necessary to assign them different tasks through the branch statement.
3.3. Child Process Recycling
Did you just have it man ps
? In general I used ps aux
grep
to add commands to find running background processes. There is a column STAT
that identifies the running state of each process. Here, we are concerned about the state Z
: Zombie (Zombie). A child process becomes a zombie process when the child process exits before the parent process, and the parent process does not do any processing on it. Oops is not the same as the shadow in the fire shadow. Naruto's Shadow is dead and then automatically disappears, but the child process here is dead and left a shell in it until the parent process reclaims it. Although the zombie process does not account for any memory, but it is very annoying, the yard of a pile of dead zombies all feel strange. (Don't forget that they also occupy the PID)
In general, the dead child process is recycled before the parent process is finished. pcntl
inside the extension there is a pcntl_wait()
function that suspends the parent process until a child process exits. If a child process becomes a zombie, it will return immediately. All the sub-processes are recycled, so it's okay to wait!
3.4. The parent process hangs first
What if the parent process hangs first? What's going to happen? Nothing will happen and the child process is still running. But at this point, the subprocess is handed over to process 1th, and process 1th becomes the stepfather of those processes. Process 1th will handle the resources of these processes well, and when they end, process 1th will automatically reclaim resources. So, another temporary way to deal with zombie processes is to close their parent processes.
4. Signal
The general multi-process thing is that the above is over, but the signal is really a very important thing in the system. The signal is the semaphore, light a signal, the program will react. You must have used this, for example, to run a program under the terminal, waiting for a half-day of no response, you may press CTRL + C to close the program. In fact, this is the signal that sends an interrupt to the program via the keyboard: SIGINT. Sometimes the process loses its response and executes the kill [PID]
command, without any other parameters, the program receives a sigterm signal. When the program receives the above two signals, it will end execution by default, so is it possible to change this default behavior? Must be able to ah!
4.1. Registration Signal
People are living procedures are also live, but the program needs to follow the rules of people to run. Now start to reset the rules for the signal, the function used here is pcntl_signal()
(why not check the PHP manual before continuing?) )。 The following procedure will redefine behavior for SIGINT, and be careful:
Defines a processor that only outputs one line of information after receiving the SIGINT signalfunctionSignalhandler($signal){If($signal==SIGINT){Echo' Signal received '.Php_eol;}}//Signal Registration: When a SIGINT signal is received, the Signalhandler () function is calledpcntl_signal (sigint< Span class= "token punctuation", ' Signalhandler ' ) while (true" {sleep (1) ; //do something pcntl_signal_dispatch (
Execute it, press CTRL + C at any time to see what happens.
4.2. Signal distribution
Note: A pcntl_signal()
function is simply a registration signal and its processing method, the real receive signal and call its processing method is the pcntl_signal_dispatch()
function. Try // do something
Replacing this code with the following:
for ( $i = 0; $i < 1000000; $i ++) {echo $i php_eol; usleep (100000;}
Execute the script under the terminal and try to press CTRL + C while it is outputting the numbers continuously. See what the program is responding to? Well...... Nothing, except the screen may be a little more ^C
, the program has been continuously output numbers. Because the program has not been executed, so there is no pcntl_signal_dispatch()
call signalHandler()
, so there is no output signal received
.
4.3. Version issues
If you carefully read the PHP document, you will find pcntl_signal_dispatch()
that this function is PHP 5.3 support, if your PHP version is greater than 5.3, it is recommended to use this method to call the signal processor. Versions below 5.3 Need to add a sentence before registering the signal: to declare(ticks = 1);
check the signal every time a low-level instruction is executed, and to call its signal processor if a registered signal is detected. It's pretty uncomfortable to think, why have you been checking it all the time? It would be nice to have a look at the place we specified.
4.4. Feel the Zombie process
Now we go back to the issue of child process recycling (almost forgot = = "). When one of your child processes hangs (or ends), the parent process is still running and may not exit for a long time. A zombie process stands up from here! At this point, the umbrella company (the kernel) found a zombie in its site, who is the son of the zombie? Look at the Ppid and you'll know. The kernel then sends a signal to the PPID process (that is, the parent process of the zombie process): SIGCHLD. Then, do you know how to reclaim this subprocess in the parent process? Hint, use the pcntl_wait()
function.
4.5. Send a signal
I hope I've just had a serious man kill
command. It actually sends a signal to the process, and in PHP it can also invoke posix_kill()
functions to achieve the same effect. With it, you can control the operation of other child processes in the parent process. For example, if all child processes are closed before the end of the parent process, then the parent process will fork
record the PID of all child processes and send the end signal to the child process in turn before the end of the parent process.
5. Practice
PHP's multi-process and C is quite similar, to understand the future in other languages to write the same thing is similar to the same situation. If you are free, try to write a small program and feel the taste of it:
- The 16-year-old Naruto sends a shadow, and divides 5 fen.
- Each clone lives 10-30 seconds at random, outputting dots per second.
- Ensure that the body can feel the end of the clone, and then start another clone, to ensure that there are up to 5 copies
- Do not use
nohup
, so that the original body can still run after the terminal is closed
- Write the number of copies (5) into a configuration file, and when sending a signal to the original (consider using SIGUSR1 or SIGUSR2), the original reads the configuration file and updates the maximum number of allowed clones
- If there is more, close a few, if less, and then split out a few
Tips:
while
ensure that the process runs with a loop, sleep
so that 100% of the CPU is not occupied
- When the terminal of the running process is closed, the program receives a SIGHUP signal
parse_ini_file()
INI configuration file can be parsed with functions
PHP Multi-Process programming preliminary