Heim >Backend-Entwicklung >PHP-Tutorial >Detaillierte Einführung in den von PHP Shared Memory verwendeten Code

Detaillierte Einführung in den von PHP Shared Memory verwendeten Code

黄舟
黄舟Original
2017-03-08 10:14:511506Durchsuche

In diesem Artikel wird erläutert, wie der prozessübergreifende Kommunikationsmechanismus IPC (Inter-Process-Communication) in der PHP4-Umgebung verwendet wird. Die in diesem Artikel besprochene Softwareumgebung ist Linux+php4.0.4 oder höher. Wir gehen zunächst davon aus, dass Sie PHP4 und UNIX installiert haben. Damit PHP4 Shared Memory und Semaphoren nutzen kann, müssen beim Kompilieren des PHP4-Programms die beiden Erweiterungsmodule shmop und sysvsem aktiviert werden.

Implementierungsmethode: Fügen Sie beim Einrichten von PHP (konfigurieren) die folgenden Optionen hinzu.

--enable-shmop --enable-sysvsem

Dadurch kann Ihr PHP-System verwandte IPC-Funktionen verarbeiten.

Was ist IPC?

IPC (Inter-Process Communication) ist ein Unix-Standardkommunikationsmechanismus, der eine Methode für die Kommunikation verschiedener Prozesse auf demselben Host untereinander bereitstellt. Es gibt drei grundlegende IPC-Verarbeitungsmechanismen: Shared Memory, Semaphore und Nachrichtenwarteschlangen. In diesem Artikel diskutieren wir hauptsächlich die Verwendung von Shared Memory und Semaphoren. Was die Nachrichtenwarteschlange betrifft, wird der Autor sie in naher Zukunft speziell vorstellen.

Verwendung von Shared-Memory-Segmenten in PHP

Die Verwendung von Shared-Memory zwischen verschiedenen Verarbeitungsprozessen ist eine gute Möglichkeit, die Kommunikation zwischen verschiedenen Prozessen zu erreichen. Wenn Sie in einem Prozess eine Information in den Shared Memory schreiben, können auch alle anderen Prozesse die geschriebenen Daten sehen. Sehr praktisch. Mithilfe des Shared Memory in PHP können Sie unterschiedliche Ergebnisse erzielen, wenn verschiedene Prozesse dasselbe PHP-Skript ausführen. Oder implementieren Sie eine Echtzeitabfrage zur Anzahl der gleichzeitig ausgeführten PHP usw.

Mit Shared Memory können zwei oder mehr Prozesse einen bestimmten Speicherbereich gemeinsam nutzen. Da keine Daten zwischen Client und Server kopiert werden müssen, ist dies der schnellste IPC-Typ. Der einzige Trick bei der Nutzung von Shared Memory ist der gleichzeitige Zugriff mehrerer Prozesse auf einen bestimmten Speicherbereich.

Wie erstelle ich ein Shared-Memory-Segment? Der folgende Code kann Ihnen beim Erstellen eines gemeinsamen Speichers helfen.

$shm_id = shmop_open($key, $mode, $perm, $size);

Beachten Sie, dass jedes Shared-Memory-Segment eine eindeutige ID hat. In PHP gibt shmop_open die ID des erstellten Shared-Memory-Segments zurück. Hier verwenden wir $ shm_id, um es aufzuzeichnen. Und $key ist ein Schlüsselwert, den wir logisch für das gemeinsam genutzte Speichersegment darstellen. Verschiedene Prozesse können dasselbe Speichersegment gemeinsam nutzen, solange sie dieselbe Schlüssel-ID wählen. Bei uns ist es üblich, den Hashwert einer Zeichenfolge (so etwas wie einen Dateinamen) zu verwenden, da die Schlüssel-ID $mode angibt, wie das gemeinsam genutzte Speichersegment verwendet wird. Da es sich um eine Neuschöpfung handelt, lautet der Wert „c“ – was „erstellen“ bedeutet. Wenn Sie auf den erstellten Shared Memory zugreifen, verwenden Sie bitte „a“, was Zugriff bedeutet. Der Parameter $perm definiert die Zugriffsberechtigungen im Oktalformat. Informationen zu Berechtigungsdefinitionen finden Sie in der Hilfe zum UNIX-Dateisystem. $size definiert die Größe des gemeinsam genutzten Speichers. Obwohl es ein bisschen wie fopen (Dateiverarbeitung) ist, sollten Sie es nicht als dasselbe wie Dateiverarbeitung betrachten. Etwas davon werden Sie später in der Beschreibung sehen.

Zum Beispiel:

$shm_id = shmop_open(0xff3, "c", 0644, 100);

Hier öffnen wir ein Shared-Memory-Segment mit einem Schlüsselwert im Format 0xff3 –rw-r—r— und einer Größe von 100 Bytes.

Wenn Sie auf ein vorhandenes Shared-Memory-Segment zugreifen müssen, müssen Sie beim Aufruf von shmop_open den 3. und 4. Parameter auf 0 setzen.

IPC-Arbeitsstatusabfrage

Unter Unix können Sie mit dem Befehlszeilenprogramm ipcs den Status aller IPC-Ressourcen im System abfragen. Einige Systemanforderungen erfordern jedoch die Ausführung durch einen Superuser. Das Bild unten ist ein Ausschnitt der ipcs-Laufergebnisse.

Im Bild oben zeigt das System 4 gemeinsam genutzte Speichersegmente an. Beachten Sie, dass der vierte Schlüsselwert 0x00000ff3 ist, der von dem PHP-Programm erstellt wurde, das wir gerade ausgeführt haben. Informationen zur Verwendung von ipcs finden Sie im UNIX-Benutzerhandbuch.

So geben Sie Shared Memory frei

Der Weg, Shared Memory freizugeben, besteht darin, den PHP-Befehl aufzurufen: shmop_delete($id)

shmop_delete($id);

$id ist der Rückgabewert von shmop_op, der beim Aufruf von shmop_open gespeichert wurde. Eine andere Möglichkeit besteht darin, UNIX-Verwaltungsbefehle zu verwenden:

ipcrm id, id ist die ID, die Sie bei der Verwendung von ipcs sehen. Sie unterscheidet sich von der $id in Ihrem Programm. Seien Sie jedoch vorsichtig, wenn Sie ipcrm verwenden, um das gemeinsam genutzte Speichersegment direkt zu löschen, kann dies dazu führen, dass andere Prozesse, die sich dieser Situation nicht bewusst sind, beim Verweisen auf diesen nicht mehr vorhandenen gemeinsam genutzten Speicher unvorhersehbare Fehler verursachen (häufig mit ungünstigen Ergebnissen).

So verwenden Sie den gemeinsam genutzten Speicher (lesen und schreiben)

Verwenden Sie die unten gezeigte Funktion, um Daten in den gemeinsam genutzten Speicher zu schreiben

int shmop_write (int shmid, string data, int offset)

Wo shmid ist das von shmop_open zurückgegebene Handle. Die Variable $Data speichert die zu speichernden Daten. $offset beschreibt die Position des Schreibens des ersten Bytes vom Anfang des gemeinsam genutzten Speichers (beginnend mit 0).

Der Lesevorgang ist:

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种:请求、释放。当你执行释放操作时, 系统将把该信号值减一。如果小于0那就还设为0。而当你执行请求操作时,系统将把该信号值加一,如果该值大于设定的最大值那么系统将挂起你的处理进程直到其他进程释放到小于最大值为止。一般情况下最大值设为1,这样一来当一个进程获得请求时其他后面的进程只能等待它退出互斥区后释放信号量才能进入该互斥区并同时设为独占方式。这样的信号量常称为双态信号量。当然,如果初值是任意一个正数就表明有多少个共享资源单位可供共享应用。

  申请、释放操作的PHP格式如下:

int sem_acquire (int sem_identifier) 申请 
int sem_release (int sem_identifier) 释放 
其中sem_identifier是调用sem_get的返回值(句柄)。  
一个简单的互斥协议例子 
下面是一段很简单的互斥操作规程。 
$semid=sem_get(0xee3,1,0666); 
$shm_id = shmop_open(0xff3, "c", 0644, 100); 
sem_acquire($semid);      //申请 
/* 进入临界区*/ 
这里,对共享内存进行处理 
sem_release($semid);      //释放

  正如你所看到的,互斥的实现很简单:申请进入临界区,对临界区资源进行操作(比如修改共享内存)退出临界区并释放信号。这样一来就可以保证在同一个时间片中不可能有同时2个进程对同一段共享内存进行操作。因为信号量机制保证一个时间片只能由一个进程进入,其他进程必须等待当前处理的进程完成后方能进入。

  临界区一般是指那些不允许同时有多个进程并发处理的代码段。

  要注意的是:在PHP中必须由同一个进程释放它所占用的信号量。在一般系统中允许进程释放别的进程占用的信号。在编写临界区代码一定要小心设计资源的分配,避免A等B,B等A的死锁情况发生。

  运 用

  IPC的运用是十分广泛的。比如,在不同进程间保存一个解释过的复杂的配置文件、或具体设置的用户等,以避免重复处理。我也曾经用共享内存的技术把一大批PHP脚本必须引用的一个很大的文件放入共享内存,并由此显著提升了Web服务的速度、消除了部分瓶颈。关于它的使用还有聊天室,多路广播等等。IPC的威力取决于你的想象力的大小。如果本文对你有一点点启发,那我不胜荣幸。愿意很你讨论这令人入迷的电脑技术。

<?php
//print_r($res_area);
//$res_area = array("username" => "yanjing5462","password" => "132");
$new_area = serialize($res_area);
//申请共享内存空间
$shm_id = @shmop_open(0xff9, "a", 0, 0);
if(empty($shm_id))
{
echo "创建";
$shm_id = shmop_open(0xff9, "c", 0700, 1048576); //10MB
//$value = "我国已成为全球能源建设规模最大的市场";
//写入共享内存空间
echo $shm_id;
shmop_write($shm_id, $new_area, 0);
  }
else
{
echo &#39;不创建&#39;.time();
shmop_delete($shm_id);
shmop_close($shm_id);
}
$shmid = shmop_open(0xff9, "a", 0, 0);
  $my_string = shmop_read($shmid, 0, 1048576);
  print_r( unserialize($my_string) );
?>

 以上就是php共享内存使用的代码详细介绍的内容,更多相关内容请关注PHP中文网(www.php.cn)!



Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn