Last week, we began our discussion of PHP standalone scripts. This week, we'll be talking about child processes, shared resources, signals, and writing daemons. The second of three parts, this article is excerpted from chapter five of the book Advanced PHP Programming, written by George Schlossnagle (Sams; ISBN: 0672325616).
PHP has no native support for threads, which makes it difficult for developers coming from thread-oriented languages such as Java to write programs that must accomplish multiple tasks simultaneously. All is not lost, though: PHP supports traditional Unix multitasking by allowing a process to spawn child processes via pcntl_fork() (a wrapper around the Unix system call fork()). To enable this function (and all the pcntl_* functions), you must build PHP with the --enable-pcntl flag.
When you call pcntl_fork() in a script, a new process is created, and it continues executing the script from the point of the pcntl_fork() call. The original process also continues execution from that point forward. This means that you then have two copies of the script running—the parent (the original process) and the child (the newly created process).
pcntl_fork() actually returns twice—once in the parent and once in the child. In the parent, the return value is the process ID (PID) of the newly created child, and in the child, the return value is 0. This is how you distinguish the parent from the child.
The following simple script creates a child process:
#!/usr/bin/env php
<?php
if($pid = pcntl_fork()) {
$my_pid = getmypid();
print "My pid is $my_pid. pcntl_fork() return $pid,
this is the parent\n";
} else {
$my_pid = getmypid();
print "My pid is $my_pid. pcntl_fork() returned 0,
this is the child\n";
}
?>
Running this script outputs the following:
> ./4.php
My pid is 4286. pcntl_fork() return 4287, this is
the parent
My pid is 4287. pcntl_fork() returned 0, this is
the child
Note that the return value of pcntl_fork() does indeed match the PID of the child process. Also, if you run this script multiple times, you will see that sometimes the parent prints first and other times the child prints first. Because they are separate processes, they are both scheduled on the processor in the order in which the operating system sees fit, not based on the parent–child relationship.