msgbartop
PHP源码分析,Zend引擎分析,Web相关技术研究,Web技术分享–左手代码 右手诗
msgbarbottom

21 Apr 08 关于PHP你可能不知道的-PHP的事件驱动化设计

最近在做一个需要用到异步PHP的项目, 翻阅PHP源码的时候,发现了三个没有用过的模块,sysvsem,sysvshm,sysvmsg,一番研究以后,受益非浅。

在PHP中有这么一族函数,他们是对UNIX的V IPC函数族的包装。

它们很少被人们用到,但是它们却很强大。巧妙的运用它们,可以让你事倍功半。

它们包括:

信号量(Semaphores)
共享内存(Shared Memory)
进程间通信(Inter-Process Messaging, IPC)

基于这些,我们完全有可能将PHP包装成一基于消息驱动的系统。

但是,首先,我们需要介绍几个重要的基础:

1. ftok

int ftok ( string pathname, string proj )
//ftok将一个路径名pathname和一个项目名(必须为一个字符), 转化成一个整形的用来使用系统V IPC的key

2. ticks

Ticks是从PHP 4.0.3开始才加入到PHP中的,它是一个在declare代码段中解释器每执行N条低级语句就会发生的事件。N的值是在declare中的directive部分用ticks=N来指定的。

function getStatus($arg){
 print_r connection_status();

 debug_print_backtrace();

}
reigster_tick_function("getStatus", true);

declare(ticks=1){

 for($i =1; $i<999; $i++){

 echo "hello";

 }

}

unregister_tick_function("getStatus");

这个就基本相当于:

function getStatus($arg){
 print_r connection_status();

 debug_print_backtrace();

}

reigster_tick_function("getStatus", true);

declare(ticks=1){

 for($i =1; $i<999; $i++){

 echo "hello"; getStatus(true);

 }

}

unregister_tick_function("getStatus");

消息,我现在用一个例子来说明,如何结合Ticks来实现PHP的消息通信。

$mesg_key = ftok(__FILE__, 'm');
$mesg_id = msg_get_queue($mesg_key, 0666);

function fetchMessage($mesg_id){

 if(!is_resource($mesg_id)){

 print_r("Mesg Queue is not Ready");

 }

 if(msg_receive($mesg_id, 0, $mesg_type, 1024, $mesg, false, MSG_IPC_NOWAIT)){

 print_r("Process got a new incoming MSG: $mesg ");

 }

}

register_tick_function("fetchMessage", $mesg_id);

declare(ticks=2){

 $i = 0;

 while(++$i < 100){

 if($i%5 == 0){

 msg_send($mesg_id, 1, "Hi: Now Index is :". $i);
 }
 }
}

//msg_remove_queue($mesg_id);

在这个例子中,首先将我们的PHP执行Process加入到一个由ftok生成的Key所获得的消息队列中。

然后,通过Ticks,没隔俩个语句,就去查询一次消息队列。

然后模拟了消息发送。

在浏览器访问这个脚本,结果如下:

Process got a new incoming MSG: s:19:"Hi: Now Index is :5";
Process got a new incoming MSG: s:20:"Hi: Now Index is :10";
Process got a new incoming MSG: s:20:"Hi: Now Index is :15";
Process got a new incoming MSG: s:20:"Hi: Now Index is :20";
Process got a new incoming MSG: s:20:"Hi: Now Index is :25";
Process got a new incoming MSG: s:20:"Hi: Now Index is :30";
Process got a new incoming MSG: s:20:"Hi: Now Index is :35";
Process got a new incoming MSG: s:20:"Hi: Now Index is :40";
Process got a new incoming MSG: s:20:"Hi: Now Index is :45";
Process got a new incoming MSG: s:20:"Hi: Now Index is :50";
Process got a new incoming MSG: s:20:"Hi: Now Index is :55";
Process got a new incoming MSG: s:20:"Hi: Now Index is :60";
Process got a new incoming MSG: s:20:"Hi: Now Index is :65";
Process got a new incoming MSG: s:20:"Hi: Now Index is :70";
Process got a new incoming MSG: s:20:"Hi: Now Index is :75";
Process got a new incoming MSG: s:20:"Hi: Now Index is :80";
Process got a new incoming MSG: s:20:"Hi: Now Index is :85";
Process got a new incoming MSG: s:20:"Hi: Now Index is :90";
Process got a new incoming MSG: s:20:"Hi: Now Index is :95";

看到这里是不是,大家已经对怎么模拟PHP为事件驱动已经有了一个概念了? 别急,我们继续完善。

2. 信号量

信号量的概念,大家应该都很熟悉。通过信号量,可以实现进程通信,竞争等。 再次就不赘述了,只是简单的列出PHP中提供的信号量函数集。

sem_acquire -- Acquire a semaphore
sem_get -- Get a semaphore id
sem_release -- Release a semaphore
sem_remove -- Remove a semaphore

具体信息,可以翻阅PHP手册。

3. 内存共享

PHP sysvshm提供了一个内存共享方案:sysvshm,它是和sysvsem,sysvmsg一个系列的,但在此处,我并没有使用它,我使用的shmop系列函数,结合TIcks

function memoryUsage(){
 printf("%s: %s<br/>", date("H:i:s", $now), memory_get_usage());

 //var_dump(debug_backtrace());

 //var_dump(__FUNCTION__);

 //debug_print_backtrace();

}

register_tick_function("memoryUsage");

declare(ticks=1){

$shm_key = ftok(__FILE__, 's');

$shm_id = shmop_open($shm_key, 'c', 0644, 100);

}

printf("Size of Shared Memory is: %s<br/>", shmop_size($shm_id));

$shm_text = shmop_read($shm_id, 0, 100);

eval($shm_text);

if(!empty($share_array)){

 var_dump($share_array);

 $share_array['id'] += 1;

}else{

 $share_array = array('id' => 1);

}

$out_put_str = "$share_array = " . var_export($share_array, true) .";";

$out_put_str = str_pad($out_put_str, 100, " ", STR_PAD_RIGHT);

shmop_write($shm_id, $out_put_str, 0);

?>

运行这个例子,不断刷新,我们可以看到index在递增。

单单使用这个shmop就能完成一下,PHP脚本之间共享数据的功能:以及,比如缓存,计数等等。

未完待续

Related Posts:

Tags: , ,

Reader's Comments

  1. |

    巧妙的运用它们,可以让你事倍功半。
    —————————————

    为什么要事倍功半丫 ,囧

  2. |

    呵呵, 事半功倍…

  3. |

    为什么我用了 register_tick_function 设置回调并且 declare(ticks = 1) 后,页面就提示 apache 错误了?救命。。。

  4. |

    哇,好东西唉~~从来没看过这些呢~

    拜一拜博主~~学习SHM和SEM中……

  5. |

    hi

    SYSVSHM, SYSVSEM, SYSVMSG就是
    shm_* sem_* , msg_* 系列函数是吧?

    另,php_event.dll这个是什么东西?有研究过么?

  6. |

    @Rodin, 恩, php_event.dll是 Pecl中event包的win32版本。
    要是使用这个那就更方便了,呵呵。

  7. |

    [...] 传统的B/S结构的应用程序,都是采用”客户端拉”结束来实现客户端和服务器端的数据交换。 本文将通过结合Ticks(可以参看我的另外一篇文章:关于PHP你可能不知道的-PHP的事件驱动化设计),来实现一个服务器推的PHP聊天室简单构想。 [...]

Leave a Comment

*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Click to hear an audio file of the anti-spam word