在PHP中使用共享内存段 在不一样的处理进程之间使用共享内存是一个实现不一样进程之间相互通信的好方法。若是你在一个进程中向所共享的内存写入一段信息,那么全部其余的进程也能够看 到这段被写入的数据。很是方便。 php
在PHP中有了共享内存的帮助,你能够实现不一样进程在运行同一段PHP脚本时返回不一样的结果。或实现对PHP同时运行数量 的实时查询等等。共享内存容许两个或者多个进程共享一给定的存储区。由于数据不须要在*户机和*务器之间复制,因此这是最快的一种IPC。使用共享内存的惟一窍门是多个进程对一给定存储区的同步存取。 数组
如何创建一个共享内存段呢?下面的代码能够帮你创建共享内存。$shm_id = shmop_open($key, $mode, $perm, $size);注意,每一个共享内存段都有一个惟一的ID, 在PHP中,shmop_open会把创建好的共享内存段的ID返回,这里咱们用$shm_id记录它。而$key是一个咱们逻辑上表示共享内存段的 Key值。不一样进程只要选择同一个Key id就能够共享同一段存储段。习惯上咱们用一个串(相似文件名同样的东西)的散列值做为key id. $mode指明了共享内存段的使用方式。 浏览器
这里因为是新建,所以值为’c’ –取create之意。若是你是访问已经创建过的共享内存那么请用’a’,-- 取access之意。$perm参数定义了访问的权限,8进制,关于权限定义请看UNIX文件系统帮助。$size定义了共享内存的大小。尽管有点象 fopen(文件处理)你可不要当它同文件处理同样。后面的描述你将看到着一点。$shm_id = shmop_open(0xff3, "c", 0644, 100); 这里咱们打开了一个共享内存段 键值0xff3 –rw-r—r—格式,大小为100字节。若是须要访问已有的共享内存段,你必须在调用shmop_open中设第三、4个参数为0。 缓存
IPC工做状态的查询 在Unix下,你能够用一个命令行程序ipcs查询系统全部的IPC资源状态。不过有些系统要求须要超级用户方能执行。下图是一段ipcs的运行结果。上图中系统显示了4个共享内存段,注意其中第4个键值为0x00000ff3的就是咱们刚刚运行过的PHP程序所建立的。关于ipcs的用法请参*UNIX用户手册。如何释放共享内存呢 释放共享内存的办法是调用PHP指令:shmop_delete($id) $id 就是你调用shmop_open所存的shmop_op的返回值。还有一个办法就是用UNIX的管理指令: ipcrm id, id就是你用ipcs看到的ID.和你程序中的$id不同。 服务器
不过要当心,若是你用ipcrm直接删除共享内存段那么有可能致使其余不知道这一状况的进程在引用这个已经不复存在的共享内存器时出现一些不可预测的错误(每每结果不妙)。如何使用(读写)共享内存呢 使用以下所示函数向共享内存写入数据 int shmop_write (int shmid, string data, int offset) 其中shmid是用shmop_open返回的句柄。$Data变量存放了要存放的数据。$offset描述了写入从共享内存的开始第一个字节的位置(以0开始)。
网络
读取操做是: string shmop_read (int shmid, int start, int count) 一样,指明$shmid,开始偏移量(以0开始)、总读取数量。返回结果串。这样,你就能够把共享内存段看成是一个字节数组。读几个再写几个,想干吗就干吗,十分方便。 多进程问题的*虑 如今,在单独的一个PHP进程中读写、建立、删除共享内存方面上你应该没有问题了。可是,显然实际运行中不可能只是一个PHP进程在运行中。若是在多个进 程的状况下你仍是沿用单个进程的处理方法,你必定会碰到问题 ---- 著名的并行和互斥问题。好比说有2个进程同时须要对同一段内存进行读写。当两个进程同时执行写入操做时,你将获得一个错误的数据,由于该段内存将之多是 最后执行的进程的内容,甚至是由2个进程写入的数据轮流随机出现的一段混合的四不象。这显然是不能接受的。 数据结构
为了解决这个问题,咱们必须引入互斥机制。互斥 机制在不少操做系统的教材上都有专门讲述,这里很少重复。实现互斥机制的最简单办法就是使用信号灯。信号量是另一种进程间通信(IPC)的方式,它同其余IPC机构(管道、FIFO、消息队列)不一样。 并发
它是一个记数器,用于控制多进程对共享数据的存储。一样的是你能够用ipcs和ipcrm实现对信号灯使用状态的查询和对其实现删除操做。在PHP中你能够用下列函数建立一个新的信号量并返回操做该信号量的句柄。若是该key指向的信号量已经存在,sem_get直接返回操做该信号量的句柄。int sem_get (int key [, int max_acquire [, int perm]]) $max_acquire 指明同时最多能够用几个进程进入该信号而没必要等待该信号被释放(也就是最大同时处理某一资源的进程数目,通常该值均为一)。$perm指明了访问权限。一旦你成功的拥有了一个信号量,你对它所能作的只有2种:请求、释放。 socket
当你执行释放操做时, 系统将把该信号值减一。若是小于0那就还设为0。而当你执行请求操做时,系统将把该信号值加一,若是该值大于设定的最大值那么系统将挂起你的处理进程直到 其余进程释放到小于最大值为止。通常状况下最大值设为1,这样一来当一个进程得到请求时其余后面的进程只能等待它退出互斥区后释放信号量才能进入该互斥区 并同时设为独占方式。这样的信号量常称为双态信号量。固然,若是初值是任意一个正数就代表有多少个共享资源单位可供共享应用。申请、释放操做的PHP格式以下:int sem_acquire (int sem_identifier) 申请 int sem_release (int sem_identifier) 释放 其中sem_identifier是调用sem_get的返回值(句柄)。正如你所看到的,互斥的实现很简单:申请进入临界区,对临界区资源进行操做(好比修改共享内存)退出临界区并释放信号。 tcp
这样一来就能够保证在同一个时间片 中不可能有同时2个进程对同一段共享内存进行操做。由于信号量机制保证一个时间片只能由一个进程进入,其余进程必须等待当前处理的进程完成后方能进入。临界区通常是指那些不容许同时有多个进程并发处理的代码段。要注意的是:在PHP中必须由同一个进程释放它所占用的信号量。在通常系统中容许进程释放别的进程占用的信号。在编写临界区代码必定要当心设计资源的分配,避免A等B,B等A的死锁状况发生。
IPC的运用是十分普遍的。好比,在不一样进程间保存一个解释过的复杂的配置文件、或具体设置的用户等,以免重复处理。我也曾经用共享内存的技术把一大批 PHP脚本必须引用的一个很大的文件放入共享内存,并由此显著提高了Web*务的速度、消除了部分瓶颈。关于它的使用还有聊天室,多路广播等等。IPC的 威力取决于你的想象力的大小。若是本文对你有一点点启发,那我不胜荣幸。愿意很你讨论这使人入迷的*脑技术。
Php.exe example01_server.php若是你没有在系统的环境变量中设置php解释器的路径,那么你将须要给php.exe指定详细的路径。当你运行这个服务器端的时候,你可以经过远程登录(telnet)的方式链接到端口1337来测试这个服务器。以下图:上面的服务器端有三个问题:1. 它不能接受多个链接。2. 它只完成惟一的一个命令。
3. 你不能经过Web浏览器链接这个服务器。
这个第一个问题比较容易解决,你可使用一个应用程序去每次都链接到服务器。可是后面的问题是你须要使用一个Web页面去链接这个服务器,这个比较困难。你可让你的服务器接受链接,而后些数据到客户端(若是它必定要写的话),关闭链接而且等待下一个链接。处理第二个问题是很容易的。你须要产生一个php页链接一个socket,发送一些数据进它的缓存并处理它。而后你又个处理后的数据在还顿,你可以发送你的数据到服务器。在另一台客户端链接,它将处理那些数据。这个例子的代码演示了客户端链接到服务器。客户端读取数据。若是这是第一时间到达这个循环的首次链接,这个服务器将发送“NO DATA”返回给客户端。若是状况发生了,这个客户端在链接之上。客户端发送它的数据到服务器,数据发送给服务器,客户端等待响应。一旦接受到响应,那么 它将把响应写到屏幕上。