佛山兄弟连IT培训学校

186-7589-7389

从并发处理谈PHP进程间通信(二)System V IPC

编辑:佛山兄弟连IT培训学校时间:2019-05-31

前言

进程间通讯是一个永远的论题,我的上一篇文章经过一个并发循环ID生成器的完结介绍了如何运用外部介质来进行进程间通讯:从并发处理谈PHP进程间通讯(一)外部介质 。介绍的几种办法适用于各种言语,可是他们都依赖于一种外部介质,文明的读写有瓶颈,mysql 和 redis 会挂掉或衔接超时,归根到底总觉得在 HACK;

关于进程间通讯,每一个完备的言语都应该有对应的处理办法,而 PHP 对应的则是一族对 UNIX SYSTEM V包装的函数,包括信号量(semaphore)、同享内存(shared memory)和音讯行列(msg queue)的操作。

它的安装和运用十分简略,在编译 PHP 时增加 --enable-sysvsem --enable-sysvshm --enable-sysvmsg 参数就能够,当然 Windows 上无法运用。

今日咱们依旧运用上一篇文章的例子来介绍 PHP 内部完结的进程间通讯,在了解它们的具体运用之前,先简略介绍一下信号量、同享内存、音讯行列的概念。

Unix System V IPC

信号量

信号量又称为信号灯,它是用来和谐不同进程间的数据目标的,而最主要的运用是同享内存办法的进程间通讯。本质上,信号量是一个计数器,它用来记录对某个资源(如同享内存)的存取状况。

一般说来,为了获得同享资源,进程需求执行下列操作:

获取操控同享资源的信号量的值;

若值为正,进程将信号量减1,进程操作同享资源,进入步骤4;

若值0,则拒绝进程运用同享资源,进程进入睡觉状况,直至信号量值大于0后,进程被唤醒,转入步骤1;

当进程不再运用同享资源时,将信号量值加1。假如此刻有进程正在睡觉等候此信号量,则唤醒此进程;

信号量的运用能够类比为:

一个房间有必要用钥匙才能开门,有N把钥匙放在门口,拿到钥匙开门进入房间,出来时将钥匙放回并奉告等候的人去取钥匙开门。 此例中,钥匙的数量约束了同一时间内涵房间的最大人数。房间即同享资源,钥匙是信号量,而想进入房间的人则是多个进程。

信号量有二值和多值之分,一般同享资源都不答应多个进程一起操作,多运用二值信号量。

同享内存

为了在多个进程间交换信息,内核专门留出了一块内存区,能够由需求访问的进程将其映射到自己的私有地址空间。进程就能够直接读写这一块内存而不需求进行数据的复制,然后大大提高功率。同享内存能够比方成一块共用黑板,每个人都能在上面留言,写东西。

到于同享内存,咱们一定要关怀其生计周期:System V 同享内存区域目标是随内核持续的,除非显式删除同享内存区域目标,即使一切访问同享内存区域目标的进程都现已正常完毕,同享内存区域目标仍然在内核中存在,在内核从头引导之前,对该同享内存区域目标的任何改写操作都将一向保存。

音讯行列

音讯行列是一条公共音讯链,音讯存取一般为先进先出(FIFO),能完结多个进程对音讯的原子操作和异步存取。音讯行列的运用十分广泛,不光是进程间通讯,流程异步化、解耦方面也运用广泛。

音讯行列则相当于一条流水线的一段,上层有多个工人把产品放入,基层有多个工人将产品取出加工。

本文的完结不包括音讯行列的运用,但关于音讯行列完结互斥锁,这儿给出一个思路:先给音讯行列初始化一个值,并发进程竞争获取此值,获取到值的进程进行同享资源的处理,进程不再同享资源时,再将此值放入行列,经过行列的原子性来确保一起只要一个进程访问同享资源。

函数介绍

ftok

int ftok ( string $pathname, string $proj )

ftok将一个途径 pathname 和一个项目名(有必要为一个字符), 转化成一个整数形的 System V IPC 键,本文介绍的 System V 通讯办法都是根据此键来完结的,此ID 值也能够自己指定一个 INT 型来断定,不必要运用 ftok 获取;

需求留意的是:ftok 的结果是经过文档的索引节点号来核算获取的,而文件的删除重建会导致其索引节点号变化,所以即使是相同的文件名,也可能会导致获取到的 IPC 键不同,所以需求尽量确保 $pathname 不变化;

semaphore函数

resource sem_get ( int $key [, int $max_acquire = 1 [, int $perm = 0666 [, int $auto_release = 1 ]]] )

获取或生成一个信号量标识,咱们留意其 max_acquire 值为 1,即确保一起只要一个进程能获取到它;auto_release 为 1 ,确保进程在非正常状况退出时能释放此信号量;

bool sem_acquire ( resource $sem_identifier [, bool $nowait = false ] )

bool sem_release ( resource $sem_identifier )

获取/释放一个信号量,留意获取信号量的 $nowait 为false,使进程在获取信号量失利后进行进程等候即可。

shared_memory函数

resource shm_attach ( int $key [, int $memsize [, int $perm = 0666 ]] )

bool shm_detach ( resource $shm_identifier )

衔接/断开 与 同享内存段的衔接 $memsize, 以字节 byte 为单位;需求留意,在第一次运用 $key 衔接内存段创立时,会初始化内存大小和权限,后续再衔接时,这两个参数会被疏忽。

bool shm_put_var ( resource $shm_identifier , int $variable_key , mixed $variable )

mixed shm_get_var ( resource $shm_identifier , int $variable_key )

向同享内存内写入或读取一个变量,需求留意变量 key 只能是 int 型;

代码完结

function getCycleIdFromSystemV($max, $min = 0) {

$key = ftok('/tmp/cycleIdFromSystemV.tok', 'd');

$var_key = 0;

$sem_id = sem_get($key);

$shm_id = shm_attach($key, 4096);

if (sem_acquire($sem_id)) {

$cycle_id = intval(shm_get_var($shm_id, $var_key));

$cycle_id++;

if ($cycle_id > $max) {

$cycle_id = $min;

}

shm_put_var($shm_id, $var_key, $cycle_id);

shm_detach($shm_id);

sem_release($sem_id);

return $cycle_id;

}

return false;

}

小结

PHP培训学校发现 PHP 对信号量和同享内存封装得很好,运用起来十分简略。除此之外,PHP 的类库 Sync 将常用 IPC 办法封装成为类,能完结跨渠道的运用,感兴趣的能够了解运用一下。

当然进程间通讯的办法和品种有很多,本文介绍的 id 递加仅仅很简略的一种,不过,知道了办法,再去把这些办法改造成为其他品种也就不难了。


上一篇:分享Eclipse php快捷键大全

下一篇:PHP培训学校分享如何解决PHP页面显示乱码问题

联系方式

选择专业时,如果犹豫不定,不知道选择哪个比较好,敬请致电,专业的咨询老师会为你解答。

  • 报名热线:186-7589-7389
  • 咨询老师:吴老师
  • 点击咨询:

友情连接:

关于我们|联系我们|网站地图

QQ咨询
在线咨询
在线报名
186-7589-7389
返回顶部