本文将讨论在PHP4环境下如何使用进程间通讯机制——IPC(Inter-Process-Communication)。本文讨论的软件环境是linux+php4.0.4或更高版本。首先,我们假设你已经装好了PHP4和UNIX, 为了使得php4可以使用共享内存和信号量,必须在编译php4程序时激活shmop和sysvsem这两个扩展模块。
实现方法:在PHP设定(configure)时加入如下选项。
--enable-shmop --enable-sysvsem
这样就使得你的PHP系统可以处理相关的IPC函数了。
IPC是什么?
IPC (Inter-process communication) 是一个Unix标准通讯机制,它提供了使得在同一台主机不同进程之间可以互相通讯的方法。基本的IPC处理机制有3种:它们分别是共享内存、信号量和消息队列。本文中我们主要讨论共享内存和信号量的使用。关于消息队列,笔者在不久的将来还会专门介绍。
在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中设第3、4个参数为0。
IPC工作状态的查询
在Unix下,你可以用一个命令行程序ipcs查询系统所有的IPC资源状态。不过有些系统要求需要超级用户方能执行。下图是一段ipcs的运行结果。
上图中系统显示了4个共享内存段,注意其中第4个键值为0x00000ff3的就是我们刚刚运行过的PHP程序所创建的。关于ipcs的用法请参考UNIX用户手册。
如何释放共享内存呢
释放共享内存的办法是调用PHP指令:shmop_delete($id)
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 プロセスを 1 つだけ実行することは当然不可能です。複数プロセスの場合でも単一プロセスの処理方法を使用すると、必ず問題が発生します。有名な並列処理と相互排他の問題です。たとえば、同じメモリを同時に読み書きする必要がある 2 つのプロセスがあるとします。 2 つのプロセスが同時に書き込み操作を実行すると、メモリ セグメントが最後に実行されたプロセスの内容であるか、2 つのプロセスが順番に書き込んだデータがランダムに混在している可能性があるため、誤ったデータが取得されます。イメージが違います。これは明らかに容認できません。この問題を解決するには、相互排除メカニズムを導入する必要があります。相互排他メカニズムについては、多くのオペレーティング システムの教科書で詳しく説明されているため、ここでは繰り返しません。相互排他メカニズムを実装する最も簡単な方法は、セマフォを使用することです。セマフォは、プロセス間通信 (IPC) の別の方法であり、他の IPC メカニズム (パイプライン、FIFO、メッセージ キュー) とは異なります。複数のプロセスによる共有データの保存を制御するために使用されるカウンターです。同様に、ipcs および ipcrm を使用して、セマフォのステータスを照会し、セマフォを削除できます。 PHP では、次の関数を使用して新しいセマフォを作成し、セマフォへのハンドルを返すことができます。キーが指すセマフォがすでに存在する場合、sem_get はセマフォを操作するためのハンドルを直接返します。
int sem_get (int key [, int max_acquire [, int perm]])
$max_acquire は、シグナルが送信されるのを待たずに、最大複数のプロセスが同時にシグナルに入ることができることを示します。 (同時に特定のリソースを処理できるプロセスの最大数です。通常、値は 1 です)。 $perm はアクセス許可を指定します。
セマフォの所有に成功したら、それに対してできることは 2 つだけです: 要求と解放です。リリース操作を実行すると、システムは信号値を 1 つ減らします。 0未満の場合は0に設定してください。要求された操作を実行すると、システムはシグナル値を 1 つ増やします。その値が設定された最大値よりも大きい場合、システムは他のプロセスが最大値未満の値に解放されるまで処理プロセスを一時停止します。通常の状況では、最大値は 1 に設定されているため、プロセスがリクエストを取得すると、後続の他のプロセスはそのリクエストがミューテックス領域から出るまで待機し、セマフォを解放してからミューテックス領域に入って排他モードに設定します。同時に。このようなセマフォは、バイナリ セマフォと呼ばれることがよくあります。もちろん、初期値が正の数値であれば、それは共有アプリケーションで使用できる共有リソース ユニットの数を示します。
アプリケーションおよびリリース操作の PHP 形式は次のとおりです。
int sem_acquire (int sem_identifier) apply
int sem_release (int sem_identifier) release
where sem_identifier sem_get (ハンドル) を呼び出したときの戻り値です。
相互排他プロトコルの簡単な例
以下は非常に簡単な相互排他操作手順です。
$semid=sem_get(0xee3,1,0666);
$shm_id = shmop_open(0xff3, "c", 0644, 100);
sem_acquire($semid); // apply
/* クリティカルセクションを入力*/
ここで、共有メモリが処理されます
sem_release($semid); //Release
ご覧のとおりはい、相互排除の実装は非常に簡単です。クリティカル セクションに入るために適用し、クリティカル セクションのリソースを操作し (共有メモリの変更など)、クリティカル セクションを終了して信号を解放します。これにより、2 つのプロセスが同じタイム スライス内の同じ共有メモリ上で動作することが不可能になります。セマフォ メカニズムにより、タイム スライスに入ることができるのは 1 つのプロセスだけであることが保証されるため、他のプロセスは、現在処理されているプロセスが完了するまで待ってから入る必要があります。
クリティカル セクションは通常、同時に複数のプロセスによる同時処理を許可しないコード セグメントを指します。
PHP では、セマフォが占有しているセマフォは同じプロセスによって解放される必要があることに注意してください。一般的なシステムでは、プロセスは他のプロセスが占有しているシグナルを解放できます。クリティカル セクションのコードを作成するときは、A が B を待ち、B が A を待つというデッドロック状況を避けるために、リソースの割り当てを慎重に設計する必要があります。
操作
IPC は広く使用されています。たとえば、説明された複雑な設定ファイルや特定のユーザー設定などを異なるプロセス間で保存して、処理の重複を回避します。また、共有メモリ テクノロジを使用して、多数の PHP スクリプトが参照する必要がある大きなファイルを共有メモリに配置しました。これにより、Web サービスの速度が大幅に向上し、いくつかのボトルネックが解消されました。用途としては、チャットルームやマルチキャストなどがあります。 IPC の力はあなたの想像力にかかっています。この記事が少しでもあなたのお役に立てれば光栄です。この魅力的なコンピューター技術についてぜひ皆さんと議論したいと思っています。メール: qwyaxm@163.net