>  기사  >  백엔드 개발  >  PHP 공유 메모리에서 사용되는 코드에 대한 자세한 소개

PHP 공유 메모리에서 사용되는 코드에 대한 자세한 소개

黄舟
黄舟원래의
2017-03-08 10:14:511447검색

이 기사에서는 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(프로세스 간 통신)는 동일한 호스트의 서로 다른 프로세스가 서로 통신할 수 있는 방법을 제공하는 Unix 표준 통신 메커니즘입니다. 기본 IPC 처리 메커니즘에는 공유 메모리, 세마포어, 메시지 큐의 세 가지가 있습니다. 이번 글에서는 주로 공유 메모리와 세마포어의 사용에 대해 논의합니다. 메시지 큐에 관해서는 저자가 가까운 시일 내에 구체적으로 소개할 예정입니다.

PHP에서 공유 메모리 세그먼트 사용

서로 다른 처리 프로세스 간에 공유 메모리를 사용하는 것은 서로 다른 프로세스 간의 통신을 달성하는 좋은 방법입니다. 한 프로세스에서 공유 메모리에 정보 조각을 쓰면 다른 모든 프로세스도 기록된 데이터를 볼 수 있습니다. 매우 편리합니다. PHP의 공유 메모리를 사용하면 서로 다른 프로세스가 동일한 PHP 스크립트를 실행할 때 서로 다른 결과를 얻을 수 있습니다. 또는 동시에 실행되는 PHP 수에 대한 실시간 쿼리를 구현합니다.

공유 메모리를 사용하면 두 개 이상의 프로세스가 특정 메모리 영역을 공유할 수 있습니다. 클라이언트와 서버 간에 데이터를 복사할 필요가 없기 때문에 가장 빠른 유형의 IPC입니다. 공유 메모리를 사용하는 유일한 방법은 주어진 메모리 영역에 여러 프로세스가 동시에 액세스하는 것입니다.

공유 메모리 세그먼트를 생성하는 방법은 무엇입니까? 다음 코드는 공유 메모리를 만드는 데 도움이 될 수 있습니다.

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

PHP에서 shmop_open은 생성된 공유 메모리 세그먼트의 ID를 반환하며 이를 기록합니다. 그리고 $key는 공유 메모리 세그먼트를 논리적으로 표현하는 Key 값입니다. 서로 다른 프로세스는 동일한 키 ID를 선택하는 한 동일한 스토리지 세그먼트를 공유할 수 있습니다. $mode는 공유 메모리 세그먼트가 사용되는 방식을 지정하기 위해 문자열의 해시 값(예: 파일 이름)을 사용하는 것이 일반적입니다. 새로운 창조이기 때문에 값은 'c', 즉 창조를 의미합니다. 생성된 공유 메모리에 접근하는 경우에는 접근을 의미하는 'a'를 사용하시기 바랍니다. $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개의 공유 메모리 세그먼트를 표시합니다. 네 번째 키 값은 방금 실행한 PHP 프로그램에 의해 생성된 0x00000ff3입니다. ipcs 사용법은 UNIX User Manual을 참고하시기 바랍니다.

공유 메모리 해제 방법

공유 메모리 해제 방법은 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进程在运行中。如果在多个进程的情况下你还是沿用单个进程的处理方法,你一定会碰到问题 ---- 著名的并行和互斥问题。比如说有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)!



성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.