- 创建进程
- 进程间通信
- 管道
- 队列
- 信号
- 其他
- 执行系统命令
- 回收
- 守护进程
- 命名进程
- CPU亲和性
swoole_process
swoole
的进程对比pcntl
扩展进程的优势:
pcntl
无法用在fpm/apache
中pcntl
没有提供进程间通信的功能pcntl
不支持重定向标准输入和输出pcntl
只提供了fork
这样原始的接口,容易使用错误swoole_process
提供了比pcntl
更强大的功能,更易用的API
,使PHP
在多进程编程方面更加轻松。
创建进程
原型:
1 2 |
int swoole_process::__construct(mixed $function, $redirect_stdin_stdout = false, $create_pipe = true); |
参数:
function
: 子进程创建成功后要执行的函数redirect_stdin_stdout
: 重定向子进程的标准输入和输出。 启用此选项后,在进程内echo
将不是打印屏幕,而是写入到管道。读取键盘输入将变为从管道中读取数据。 默认为阻塞读取。create_pipe
: 是否创建管道,启用redirect_stdin_stdout
后,此选项将忽略用户参数,强制为true
如果子进程内没有进程间通信,可以设置为false
返回值:
swoole_process
对象,数据结构包括了管道描述符和回调函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
$process = new swoole_process(function (swoole_process $worker) { echo "process: echo 1"; print_r($worker); }); $pid = $process -> start(); echo "pid:", $pid, "\n"; /* pid:12057 process: echo 1 swoole_process Object ( [pipe] => 4 [callback] => Closure Object ( [parameter] => Array ( [$worker] => <required> ) ) [pid] => 12167 ) */ |
进程间通信
管道
当创建进程时,进行了输入输出重定向,swoole
就会帮我们自动创建管道。
1 2 3 4 5 6 7 8 9 10 11 |
$process = new swoole_process(function (swoole_process $worker) { echo "process: echo 1"; }, true); $pid = $process -> start(); echo "pid:", $pid, "\n"; /* pid:12057 */ |
这里运行程序并不会输出process: echo 1
。因为输出意见被输入到管道中去了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
$process = new swoole_process(function (swoole_process $worker) { echo "process: echo 1"; }, true); $pid = $process -> start(); echo "pid:", $pid, "\n"; echo $process -> read(); /* pid:12057 process_1.php */ |
这里我们关闭输出输入重定向,并且开启管道。进行一个简单的案例说明:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
$process = new swoole_process(function (swoole_process $worker) { echo $worker -> read(), "\n"; $worker -> write("hello parent, I'm child #" . $worker->pid); $worker -> exit(0); }, false, true); $pid = $process -> start(); $process -> write("hello, child #".$pid.", I'm parent"); echo $process -> read(), "\n"; /* hello, child #12197, I'm parent hello parent, I'm child #12197 */ |
队列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
$process = new swoole_process(function (swoole_process $worker) { echo $worker -> pop(), "\n"; $worker -> push("hello parent, i'm child #".$worker->pid); $worker->exit(0); }, false); $process->useQueue(); $pid = $process->start(); $process->push("hello child #{$pid}, i'm parent"); echo $process -> pop(), "\n"; $ret = swoole_process::wait(); print_r($ret); /* hello child #23747, i'm parent hello parent, i'm child #23747 Array ( [code] => 0 [pid] => 23749 [signal] => 0 ) */ |
信号
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
$process = new swoole_process(function (swoole_process $worker) { /** * 注册信号 * 当前进程被kill触发 */ swoole_process::signal(SIGTERM, function($signal_num) use ($worker) { echo "signal SIGTERM call = $signal_num, #{$worker -> pid}\n"; // todo something $worker -> exit(0); }); for ($i=0; $i < 100000000; $i++) { } }, false); /** * 注册信号 * 子进程被kill触发 */ swoole_process::signal(SIGCHLD, function($signal_num) use ($process) { echo "signal SIGCHLD call = $signal_num, #{$process -> pid}\n"; /** * 回收子进程 */ while($ret = swoole_process::wait(false)) { echo "PID={$ret['pid']}\n"; } }); $pid = $process->start(); swoole_process::kill($pid); # kill 子进程 |
父进程中注册信号(子进程被kill触发),自进程中注册信号(本身被kill触发)。
开启子进程后,父进程立即杀死子进程,触发子进程信号事件。子进程关闭后,触发父进程信号事件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
# 信号类型列表 编号 信号名称 缺省动作 说明 1 SIGHUP 终止 终止控制终端或进程 2 SIGINT 终止 键盘产生的中断(Ctrl-C) 3 SIGQUIT dump 键盘产生的退出 4 SIGILL dump 非法指令 5 SIGTRAP dump debug中断 6 SIGABRT/SIGIOT dump 异常中止 7 SIGBUS/SIGEMT dump 总线异常/EMT指令 8 SIGFPE dump 浮点运算溢出 9 SIGKILL 终止 强制进程终止 10 SIGUSR1 终止 用户信号,进程可自定义用途 11 SIGSEGV dump 非法内存地址引用 12 SIGUSR2 终止 用户信号,进程可自定义用途 13 SIGPIPE 终止 向某个没有读取的管道中写入数据 14 SIGALRM 终止 时钟中断(闹钟) 15 SIGTERM 终止 进程终止 16 SIGSTKFLT 终止 协处理器栈错误 17 SIGCHLD 忽略 子进程退出或中断 18 SIGCONT 继续 如进程停止状态则开始运行 19 SIGSTOP 停止 停止进程运行 20 SIGSTP 停止 键盘产生的停止 21 SIGTTIN 停止 后台进程请求输入 22 SIGTTOU 停止 后台进程请求输出 23 SIGURG 忽略 socket发生紧急情况 24 SIGXCPU dump CPU时间限制被打破 25 SIGXFSZ dump 文件大小限制被打破 26 SIGVTALRM 终止 虚拟定时时钟 27 SIGPROF 终止 profile timer clock 28 SIGWINCH 忽略 窗口尺寸调整 29 SIGIO/SIGPOLL 终止 I/O可用 30 SIGPWR 终止 电源异常 31 SIGSYS/SYSUNUSED dump 系统调用异常 |
其他
执行系统命令
1 2 3 4 5 6 7 8 9 10 |
$process = new swoole_process(function (swoole_process $worker) { $worker -> exec('/bin/ps', ['-ef']); }, false); $pid = $process->start(); swoole_process::wait(); |
会输出 ps -ef
执行后内容。
回收
子进程结束必须要执行wait
进行回收,否则子进程会变成僵尸进程
守护进程
使当前进程脱变为一个守护进程。
1 2 3 4 5 6 7 |
swoole_process::daemon(); while (true) { echo "hello"; sleep(1); } |
命名进程
1 2 3 4 5 6 7 8 9 10 11 12 |
$process = new swoole_process(function (swoole_process $worker) { $worker -> name('child_namne_process_#' . $worker->pid); sleep(10); }, false); $pid = $process->start(); swoole_process::wait(); |
1 2 3 4 5 6 |
ps -ef root 24211 11981 0 16:48 pts/2 00:00:00 php process_name.php root 24212 24211 0 16:48 pts/2 00:00:00 child_namne_process_#24212 |
CPU亲和性
设置CPU亲和性,可以将进程绑定到特定的CPU核上。