Envious of Naruto Naruto's shadow? Yes, PHP programs can be used to start the shadow of the Avatar! Want to complete the task, and feel that a process is too slow, then, try a lot of process to do it. This article will explain the basic requirements of the PHP multi process, how to create multiple processes and basic signal control, and will not tell you how to do interprocess communication and information sharing for the time being.
1. Prepare
Before you do, make sure you're not using the m$ Windows platform (because I don't have windows). Linux/bsd/unix should be all fine. Check the working environment and see if we have all the PHP modules we need. Open the terminal and enter the following command:
Copy Code code as follows:
This command checks and prints all open extensions for the current PHP, looking at whether Pcntl and POSIX are in the output list.
1.1. Pcntl
If Pcntl is not found, it is probably not compiled to compile this extension. If you are the same as me compiling installed PHP, then you need to recompile the installation of PHP. Remember to add the--ENABLE-PCNTL parameter when configuring.
Copy Code code as follows:
$ 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--disable-posix when compiling.
2. Preliminary knowledge
Before you go on, you'll need to know a little bit about Linux's multiple processes. What happens to multiple processes? It's a little bit different from the shadow in Naruto. First, Naruto grew to large, such as 16 years old, cough. One day he launched a shadow and divided 5 of him. Obviously, these are also 16-year-old Naruto, not just born and don't Know Will cry baby (that is called cloning). And then, the different places come: The people who are independent are each to do their own thing, and they no longer know what the other parts and the body have done (certainly not the same as in the cartoon experience to the original body). Unless, they communicate with each other, otherwise, only 16 years old before the thing is their common memory.
A classmate said, boss you do not pit dad? I didn't watch the Naruto! Well, you can go and see it again.
Finally, the preparation of the knowledge is over, is to get a general understanding of the main process out of the child process is going on. The code of the child process is exactly the same as the main process, and part of the same thing is all that is done until the shadow is launched.
3. The operation of Shadow
So how can you understand the contents of a reel without a little bit of basic knowledge? Open the scroll first saw a word: fork.
3.1. Fork
Fork? The fork is forked, one becomes multiple! That's pretty much what it means. This command is used to create the child process. You need to use the Pcntl_fork () function here. (You can take a quick look at the PHP manual's introduction to this function.) ) to create a PHP script:
Copy Code code as follows:
$pid = Pcntl_fork (); Once the call succeeds, things get a little different.
if ($pid = = 1) {
Die (' fork failed ');
else if ($pid = = 0) {
} else {
}
The Pcntl_fork () function creates a child process, and the only difference between the child process and the parent process is that the PID (process ID) differs from the PPID (parent process ID). View the process under the terminal using the PS command (ask the man to see how PS is used: Man PS). When the function returns a value of-1, it indicates that fork failed. Try adding a phrase before if: echo $pid. Php_eol;. Run your script, the output may look like this (the result is that the child process and the parent process code are the same):
Copy Code code as follows:
67789 # This is the parent process printing
0 # This is the child process printing
When the Pcntl_fork () function call succeeds, the PID of the child process is returned in the parent process, and 0 is returned in the child process. Therefore, the following directly uses the IF branch to control the parent process and the subprocess to do different things.
3.2. Assigning tasks
Then let's talk about Naruto's 16-year-old avatar, assigning two simple output tasks to both the body and the Avatar:
Copy Code code as follows:
$parentPid = Getmypid (); This is the memory of the legend before 16 years old.
$pid = Pcntl_fork (); Once the call succeeds, things get a little different.
if ($pid = = 1) {
Die (' fork failed ');
else if ($pid = = 0) {
$mypid = Getmypid (); To get the PID of the current process with the Getmypid () function
Echo ' I am child process. My PID is '. $mypid. ' And my father ' s PID is '. $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;
}
This may be the result of the output:
Copy Code code as follows:
Oh my god! I am a Father now! My child ' s PID are 68066 and mine is 68065
I am child process. My PID are 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 subprocess, and another program gets a $pid value greater than 0, which is the PID of the subprocess, which is the parent process. In the following branch statement, different code is run because of the difference in $pid values. Again, the code for the subprocess is the same as the parent process. So it is necessary to assign them different tasks by branching statements.
3.3. Child Process Recycling
Did you just have man PS? I usually use PS aux plus grep command to find the running background process. There is a column of stat that identifies the running state of each process. Here, we focus on State Z: Zombies (Zombie). When a child process exits before the parent process, and the parent process does nothing with it, the subprocess becomes a zombie process. Oops is different from the shadow in the fire. Naruto's shadow is dried up and disappears automatically, but the child process here is dead. There is still an empty shell in it, until the parent process reclaims it. Although the zombie process does not account for what memory, but very unsightly, the yard a bunch of lying zombies feel strange. (Don't forget they're still hogging the PID.)
In general, it is OK to recycle the dead subprocess before the parent process ends. Within the pcntl 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 child processes have to be recycled, so it's okay to wait a little.
3.4. The parent process hangs up first.
What if the parent process hangs first? What's going to happen? Nothing is going to happen, and the child process is still running. But this time, the subprocess will be handed over to number 1th, and process 1th becomes the stepfather of these processes. The 1th process will handle the resources of these processes well, and the 1th process will automatically recycle resources when they end. So another temporary way to deal with zombie processes is to close their parent processes.
4. Signal
The general process of things mentioned above is over, but the signal in the system is indeed a very important thing. The signal is the semaphore, light a signal, the program will respond. This you must have used, for example, run a program under the terminal, wait a long time also no response, you may press CTRL + C to close the program. In fact, this is where the keyboard sends an interrupt signal to the program: SIGINT. Sometimes the process loses its response and executes the kill [PID] command, and the program receives a SIGTERM signal without any additional parameters. Is it possible to change the default behavior when the program receives the two signals above and ends the execution by default? Must be able to ah!
4.1. Registration Signal
A person is a living program is also alive, but the program needs to follow the rules set by people to run. Now start to reset the rules for the signal, the function used here is pcntl_signal () (Why don't you check the PHP manual before proceeding?) )。 The following procedure will redefine the behavior of the SIGINT, and watch out for:
Copy Code code as follows:
Defines a processor that outputs only one line of information after receiving a SIGINT signal
function Signalhandler ($signal) {
if ($signal = = SIGINT) {
Echo ' Signal received '. Php_eol;
}
}
Signal registration: When the SIGINT signal is received, the Signalhandler () function is called
Pcntl_signal (SIGINT, ' Signalhandler ');
while (true) {
Sleep (1);
Do something
Pcntl_signal_dispatch (); When a signal is received, call the registered Signalhandler ()
}
Execute it, press CTRL + C at any time to see what happens.
4.2. Signal distribution
Note: the Pcntl_signal () function is simply a registration signal and its processing method, the Pcntl_signal_dispatch () function is the one that actually receives the signal and calls its processing method. Try replacing/do something with the following code:
Copy Code code as follows:
for ($i = 0; $i < 1000000; $i + +) {
Echo $i. Php_eol;
Usleep (100000);
}
Execute the script under the terminal and try to press CTRL + C as it outputs the numbers. See what the program is responding to? Well...... Nothing, except that the screen may be a ^c, the program has been constantly outputting numbers. Because the program has not been executed to Pcntl_signal_dispatch (), so there is no call to Signalhandler (), so there is no output signal received.
4.3. Version problem
If you look at the PHP document carefully, you will find that pcntl_signal_dispatch () This function is PHP more than 5.3 to support, if your PHP version is greater than 5.3, it is recommended to use this method call signal processor. The version below 5.3 needs to be preceded by a sign of the registration signal: DECLARE (ticks = 1); For each low-level instruction, check the signal and call its signal processor if a registered signal is detected. It's kind of annoying to think about it, why do you keep checking it? It's better to check it out at our designated place.
4.4. Feel the Zombie process
Now we're back to the problem of child process recycling (almost forgetting = = "). 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 has stood up ever since! At this time, Umbrella Corporation (the core) found that there is a zombie in its territory, who is this zombie son? Look at the Ppid and you'll know. The kernel then sends a signal to ppid this process (the parent process of the zombie process): SIGCHLD. Then, do you know how to recycle the child process in the parent process? Hint, use the pcntl_wait () function.
4.5. Send Signal
Hope just had a serious man over kill command. It is actually sending signals to the process, and you can also invoke the Posix_kill () function in PHP 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 parent process ends, then when the parent process fork the PID of all the child processes, the parent process sends an end signal to the subprocess in turn.
5. Practice
PHP is a lot of process and C is quite similar to understand the future in other languages are similar to the same kind of situation. If you have free time, try to write a small program, to experience the taste of the flavor:
The 1.16-year-old Naruto sent a shadow, divided 5 of them
2. Each second is randomly surviving for 10-30 seconds and outputting points every
3. Ensure that the original body can feel the end of the second, and then start another one, to ensure that up to 5
4. Do not use nohup, so that the original body can still run after the terminal shutdown
5. Write the number of copies (5) into a profile and send a signal to the original (consider using SIGUSR1 or SIGUSR2) to read the configuration file and update the maximum number of copies allowed
6. If more than a few, close a few;
Tips:
1. Use while loop to ensure that the process runs, pay attention to sleep in order to avoid 100% CPU consumption
2. When the terminal of the running process is closed, the program receives a SIGHUP signal
3. You can use the Parse_ini_file () function to resolve the INI configuration file