PHP uses pcntl and libevent to implement the Timer function. Let’s look at the example first. pcntl (PHP thread) is explained below.
PHP extends pcntl to implement "multi-threading" (process)
pcntl and ticks
ticks through declare(ticks = n) {statement} 语法定义的 , declare 语法目前只能接受 ticks, 他定义的 ticks = n 的意义是当 declare 指定的语句块中执行了 N 条低级语句去发生一个事件 , 这个事件可以通过 register_tick_function($function_name) 来注册 .
pcntl 的信号机制是基于 ticks 机制实现的 . 因此 , 我们使用 pcntl 族函数中信号相关的函数时 , 需要在前面增加 declare(ticks = n) 语法结构 .
int pcntl_alarm(int $seconds):
$seconds 秒后向进程发送一个 SIGALRM 信号 , 每次调用 pcntl_alarm 方法都会取消之前设置的时钟 .
void pcntl_exec(string $path[, array $args[, array $env]]):
在当前进程空间执行一个程序 .
$path: 必须是二进制可执行文件 , 或具有有效脚本头信息 (#!/usr/local/bin/php) 的脚本文件路径 .
$args: 将要传递给该程序的字符串参数列表 ( 数组形式 )
$envs: 环境变量 . 以数组 (key => value 形式 ) 方式传递给要执行程序的环境变量 .
int pcntl_for k (void):
创建一个子进程 , 该子进程与父进程仅仅是 PID( 进程号 ) 和 PPID( 父进程号 ) 不同 .
在父线程执行时返回创建的子进程 pid, 在子线程执行时返回 0, 创建子进程失败时会在父进程上下文返回 -1, 并引发 php 错误 .
理解这里的 fork 需要知道 : pcntl_fork 创建的是一个分支节点 , 相当于一个标记 , 父进程完成后 , 子进程会从标记处继续执行 , 也就是说 pcntl_fork 后面的代码分别被父进程和子进程执行了两遍 , 而两个进程在执行过程中得到的返回值是不同的 . 因此 , 才可以分离父子进程执行不同的代码 .
int pcntl_getpriority([int $pid = getmypid()[, int $process_identifier = PRIO_PROCESS]]):
获取给定 $pid 对应的进程的优先级 , 默认是通过 getmypid() 获取到的值也就是当前进程 .
$pid: 如果没有指定 , 默认是当前进程 .
$process_identifier: PRIO_PGRP, PRIO_USER, PRIO_PROCESS 三者之一 , 默认 PRIO_PROCESS. 其中 PRIO_PGRP 指获取进程组的优先级 , PRIO_USER 指获取用户进程的优先级 , PRIO_PROCESS 指获取特定进程优先级 .
返回进程的优先级 , 或者在发生错误时返回 false, 值越小说明越优先
bool pcntl_setpriority(int $priority[, int $pid = getmypid()[, int $process_identifier = PRIO_PROCESS]]:
设置进程的优先级 .
$priority: 优先级值 , -20 到 20 的范围内 , 默认优先级为 0. 值越小说明越优先 .
$pid: 如果没有指定 , 指当前进程
$process_identifier: 意义同 pcntl_getpriority 的 $process_identifier.
设置成功返回 TRUE, 失败返回 FALSE.
bool pcntl_signal_dispatch(void):
调用通过 pcntl_signal() 安装的即将发生的信号的处理器 .
调用成功返回 TRUE, 失败返回 false.
php 5.3.3 加入
bool pcntl_signal(int $signo, callback $handler[, bool $restart_syscalls = true]):
为指定的信号 $signo 安装一个新的信号处理器 $handler.
最后一个参数不明白意义 .
bool pcntl_sigprocmask(int $how, array $set[, array &$oldset]):
增加 , 删除或设置锁信号 , 具体的行为依赖于 $how 参数
$how: SIG_BLOCK 用于把信号增加到当前锁信号中 , SIG_UNBLOCK 用于把信号从当前锁信号中移除 , SIG_SETMASK 用于用给定的信号列表替换当前锁信号 .
$set: 要增加 , 移除或设置的信号列表 .
$oldset: 用于向调用者返回旧的锁定信号 .
成功返回 TRUE, 失败返回 FALSE.
int pcntl_sigtimedwait(array $set[, array &$siginfo[, int $seconds = 0[, int $nanoseconds = 0]]]):
pcntl_sigtimedwait 实际上和 pcntl_sigwaitinfo() 所做的是同样的事情 , 不过 pcntl_sigtimedwait 多了两个增强的参数 $seconds 和 $nanoseconds, 这样就允许脚本的停留时间有一个上限而不是无限制等待 .
$set: 需要等待的信号列表
$siginfo: 用来向调用者返回等待得到的信号的信息 , 信息内容见 pcntl_sigwaitinfo
$seconds: 超时的秒数
$nanoseconds: 超时的纳秒数
成功后 , pcntl_sigtimedwiat() 返回信号编号
int pcntl_sigwaitinfo(array $set[, array &$siginfo]):
挂起当前脚本的执行 , 直到接受到 $set 中的某个信号 , 如果其中的一个信号将要到达 ( 比如被 pcntl_sigprocmask 锁定 ) 那么 pcntl_sigwaitinfo 将会立刻返回
$set: 等待的信号列表
$siginfo: 用来向调用者返回等待得到的信号的信息 , 该信息包含以下内容 :
1. 所有信号都有以下三个信息 :
a) signo: 信号编号
b) errno: 错误号
c) code: 信号代码
2. SIGCHLD 信号特有的信息
a) status: exit value or signal
b) utime: user time spent
c) stime: system time spent
d) pid: sending process id
e) uid: the real identity of the sending process User id
3. Information owned by SIGILL, SIGFPE, SIGSEGV, SIGBUS
a) addr: memory location where the fault occurred
4. SIGPOLL unique information:
a) band: band event, meaning Unknown
b) fd: File descriptor
The function runs successfully and returns the signal number
int pcntl_wait(int &$status[, int *options = 0]):
Suspend the current process until a child The process exits or until a signal requires the current process to be terminated or a signal handling function is called. If the child process has exited when called (commonly known as a zombie process), this function will return immediately and all system resources will be released.
$status is used to save the status information of the child process, which is generated by the following functions: pcntl_wifexited, pcntl_wifstopped, pcntl_wifsignaled, pcntl_wexitstatus, pcntl_wtermsig, pcntl_wstopsig.
$options: If your system allows wait3 (most BSD classes system), you can provide an optional options parameter. If this parameter is not provided, wait will use the system call. If the system does not allow wait3, providing this parameter will have no effect. The value of $options can be 0 or WNOHANG. and WUNTRACED two constants.
The function returns the PID of the exiting child process, or -1 on error, or 0 if WNOHANG is provided as option (wait3 unavailable system) and there is no valid child process
Zombie Process: Since the parent process cannot predict when the child process will end after forking, in order to leave some information to the parent process, the child process will leave a data structure called a zombie, waiting for the parent process to initiate a wait operation. It collects corpses. The period between the end of the child process (logical end) and the period before the death of the parent process is called a zombie process. After the parent process ends, all child processes will be handed over to Init. Therefore, if the parent process end, the zombie processes will be recycled. However, if the parent process never ends, these zombie processes will always occupy the process number. If the system process number is exhausted, it will result in the inability to start a new process. Therefore, the safe way is to start the new process in the parent process. Collect the corpses of the child processes generated by yourself.
int pcntl_waitpid(int $pid, int &$status[, int $options = 0]):
Suspend the current process until the child process with the given $pid exits , or the current process receives an exit signal, or receives an ige signal to call a signal processor.
If the child process corresponding to the given $pid has exited (zombie state) when calling this function, the function returns immediately , all system resources are released.
$pid: process number, less than -1 indicates that it is waiting for any child process in the process group, and the process group number is the absolute value of $pid. Equal to -1 indicates that it is waiting for any Forbidden City, The behavior is consistent with the pcntl_wait function. Equal to 0 means waiting for the child process in the same group as the calling process, and greater than 0 means it is a specific process.
$status: used to return the child process status from the function. This status information is generated by the following function : pcntl_wifexited, pcntl_wifstopped, pcntl_wifsignaled, pcntl_wexitstatus, pcntl_wtermsig, pcntl_wstopsig.
$options: The same meaning as pcntl_wait’s $options
int pcntl_wexitstatus(int $status):
Returns an interrupted subroutine process return code, This function is only useful when the pcntl_wifexited function returns TRUE. The
$status parameter is the status information generated by pcntl_waitpid.
bool pcntl_wifexited(int $status):
Checks whether the given status indicates that the child process exited normally .
bool pcntl_wifsignaled(int $status):
Check whether the given status indicates that the child process exited due to receiving a signal.
bool pcntl_wifstopped(int $status):
Check $status Whether it can indicate that the child process is currently stopped, this function is only effective when acting on the $status generated when the pcntl_waitpid function uses WUNTRACED as the value of the $options parameter.
int pcntl_wstopsig(int $status):
Passed Analyzing $status returns the number of the signal that caused the child process to stop. This function is only valid when pcntl_wifsignaled returns TRUE.
int pcntl_wtermsig(int $status):
Returns the number of the signal that caused the process to interrupt. This function is only available when pcntl_wifsignaled returns TRUE. Valid only when pcntl_wifsignaled returns TRUE.