计算机系统应用教程网站

网站首页 > 技术文章 正文

54、php利用信号实现父子进程间通信

btikc 2024-10-12 11:14:51 技术文章 10 ℃ 0 评论

1、父子进程通过信号通信

1.1、流程图如下

2、案例

2.1、源码

<?php

/**

* Copyright (C) Iamasb

* @project : 3、workerman相关知识点

* @explain : 父子进程信号通信

* @filename : 27、父子进程信号通信.php

* @author : iamasb 2801616735@qq.com

*/

// 固定进程数

$count = 2;

// 存放进程数组

$pidArr = array();

$masterPid = posix_getpid();

// 注册信号

pcntl_signal(SIGQUIT,"sigFunc",false);

function sigFunc($sig){

global $pidArr,$masterPid;

$pid = posix_getpid();

$ppid = posix_getppid();

switch($sig){

case SIGQUIT:

if( count($pidArr) && ($pid == $masterPid) ){

echo "master-->",PHP_EOL;

foreach ( $pidArr as $k=>$v ){

posix_kill($v,SIGQUIT);

unset($pidArr[$k]);

}

}else{

echo "pid = {$pid} ppid={$ppid} ",PHP_EOL;

exit;

}

break;

}

}

for($i=0;$i<$count;$i++){

$pid = pcntl_fork();

if( $pid > 0 ){

// 父进程

$pidArr[$i] = $pid;

}elseif ($pid == 0){

// 子进程

echo "子进程pid-->".posix_getpid().PHP_EOL;

while( 1 ){

pcntl_signal_dispatch();

sleep(2);

}

exit;

}else{

exit("fork fail.");

}

}

echo "父进程id->",$masterPid,PHP_EOL;

print_r($pidArr);

// 父进程监控

while(1){

pcntl_signal_dispatch();

// 阻塞获取正常退出的子进程id

$pid = pcntl_wait($status,WUNTRACED);

pcntl_signal_dispatch();

if( $pid > 0 ){

echo "{$pid} is over",PHP_EOL;

}

if (empty($pidArr)) {

echo 'master is over';

exit;

}

}

2.2、执行结果

  • 新开shell终端,执行kill命令,kill -s SIGQUIT 17304
  • kill父进程 kill -s SIGQUIT 17303

3、注意事项

知识点: 信号是可以中断 wait 等系统调用的

在源码中,pcntl_signal函数的第三个参数设置为false,这个参数是代表进程在收到信号后是内核是否重启系统调用,默认是true。也就是说,当收到主进程收到信号后,pcntl_wait立即被中断并返回了-1。这里的-1是代表异常出错。而这个异常是因为主进程收到信号后,中断了wait操作。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表