shm_attach

(PHP 4, PHP 5, PHP 7)

shm_attachCreates or open a shared memory segment

Описание

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

shm_attach() returns an id that can be used to access the System V shared memory with the given key, the first call creates the shared memory segment with memsize and the optional perm-bits perm.

A second call to shm_attach() for the same key will return a different shared memory identifier, but both identifiers access the same underlying shared memory. memsize and perm will be ignored.

Список параметров

key

A numeric shared memory segment ID

memsize

The memory size. If not provided, default to the sysvshm.init_mem in the php.ini, otherwise 10000 bytes.

perm

The optional permission bits. Default to 0666.

Возвращаемые значения

Returns a shared memory segment identifier.

Список изменений

Версия Описание
5.3.0 This function now returns a resource instead of an integer.

Примечания

Замечание:

This function used to return an integer value prior to PHP 5.3.0. To achieve the same value in a portable manner, the return value can be cast to an integer like:

<?php
// Create a temporary file and return its path
$tmp tempnam('/tmp''PHP');

// Get the file token key
$key ftok($tmp'a');

// Attach the SHM resource, notice the cast afterwards
$id shm_attach($key);

if (
$id === false) {
    die(
'Unable to create the shared memory segment');
}

// Cast to integer, since prior to PHP 5.3.0 the resource id 
// is returned which can be exposed when casting a resource
// to an integer
$id = (integer) $id;
?>

Смотрите также

  • shm_detach() - Disconnects from shared memory segment
  • ftok() - Convert a pathname and a project identifier to a System V IPC key

Коментарии

Objects are stored serialized in shm_put_var, so to find a value for memsize, you can use strlen(serialize($object_to_store_in_shm)).
1999-02-12 21:04:36
http://php5.kiev.ua/manual/ru/function.shm-attach.html
Notice that 'int key' for shared-memory is shared with the keys used for semaphores. So you get in trouble when you use the same key value for semaphores and shared memory!
1999-03-25 07:40:16
http://php5.kiev.ua/manual/ru/function.shm-attach.html
With Sun Solaris 2.x, the MAXIMUM shared memory value allowed is 1,048,576.  The maximum allowed value can be determined using the command /usr/sbin/sysdef.  On Linux, there does not seem to be any system enforced maximum size.  To change the maximum allowed size on Solaris 2.x, use set shmsys:shminfo_shmmax=[new value].
1999-09-10 16:50:52
http://php5.kiev.ua/manual/ru/function.shm-attach.html
Finding out shared memory kernel settings in FreeBSD:

sys1# sysctl -a | grep -i SHM

kern.ipc.shmmax: 4194304
kern.ipc.shmmin: 1
kern.ipc.shmmni: 96
kern.ipc.shmseg: 64
kern.ipc.shmall: 1024
kern.ipc.shm_use_phys: 0

Shows us that we can allocate a total of 4GB (wow) of shared memory, etc...
2001-01-25 06:30:35
http://php5.kiev.ua/manual/ru/function.shm-attach.html
4194304 means 4 MB and NOT 4 GB for shared memory on FreeBSD. You can increase the shared memory at runtime if you like.
2001-03-21 14:41:46
http://php5.kiev.ua/manual/ru/function.shm-attach.html
The memsize needed for shared memory (tested on linux system) can be calculated with:

For each varialbe you want to store: 24 Bytes
+ serialized var-size (see below) alligned by 4 Bytes
+ 16 Bytes

For a update of a var with the same key, the memory for the old var will be needed extra.
2002-01-18 10:36:04
http://php5.kiev.ua/manual/ru/function.shm-attach.html
Автор:
Here is an example of how to use one shared memory block to store multiple variables or arrays.. unfortunetly in order to store more than ONE variable, you have to use sem_get() multiple times.. same goes for shm_attach(), shm_put_var() and shm_get_var()

#!/usr/local/bin/php -q
<?PHP
// test.php

$SHM_KEY ftok(__FILE__,'A');

$shmid  sem_get($SHM_KEY10240644 IPC_CREAT);
$shmid2 sem_get($SHM_KEY10240644 IPC_CREAT);
$shmid3 sem_get($SHM_KEY10240644 IPC_CREAT);

$data shm_attach($shmid1024);
$data2 shm_attach($shmid21024);
$data3 shm_attach($shmid31024);

$test = array("hello","world","1","2","3");
$test2 = array("hello","world","4","5","6");
$test3 = array("hello","world","7","8","9");

shm_put_var($data,$inmem,$test);
shm_put_var($data2,$inmem2,$test2);
shm_put_var($data3,$inmem3,$test3);

print_r(shm_get_var($data,$inmem));
print_r(shm_get_var($data2,$inmem2));
print_r(shm_get_var($data3,$inmem3));

shm_detach($data);
shm_detach($data2);
shm_detach($data2);
?>

to REALLY test it.. create a second script like so and run it..

#!/usr/local/bin/php -q
<?PHP
// test2.php

$SHM_KEY ftok(__FILE__,'A');

$shmid  sem_get($SHM_KEY10240644 IPC_CREAT);
$shmid2 sem_get($SHM_KEY10240644 IPC_CREAT);
$shmid3 sem_get($SHM_KEY10240644 IPC_CREAT);

$data shm_attach($shmid1024);
$data2 shm_attach($shmid21024);
$data3 shm_attach($shmid31024);

print_r(shm_get_var($data,$inmem));
print_r(shm_get_var($data2,$inmem2));
print_r(shm_get_var($data3,$inmem3));

shm_detach($data);
shm_detach($data2);
shm_detach($data2);
?>

As you can see, test2.php doesn't insert anything into shared memory.. yet it pulls out 3 totally different arrays already stored..

Hope that helps.. took me a bit to get it right.. everyone seems to have their own idea of how shm should be used. lol.

BTW, not sure how the ftok works to be honest, cause I didn't change the __FILE__ to match the file path of test.php or anything.. I would think that the file path out have to be the exact same to work correctly.. oh well, it worked as-is! haha..

- Cecil
2004-03-18 02:37:54
http://php5.kiev.ua/manual/ru/function.shm-attach.html
As far as I see from the sources of ext/sysvshm, it's not needed to  do  arithmetic (bit) OR (|) of "perm" with  IPC_CREAT (and IPC_EXCL). The extension will do it for you. It tries to attach to the memory segment and if the try did not succeed it tries to attach but with flags set to user_flag | IPC_CREAT | IPC_EXCL.
The exact code (shm_flag is the third param to the function) :
if ((shm_id = shmget(shm_key, 0, 0)) < 0) {
      if (shm_size < sizeof(sysvshm_chunk_head)) {
            php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed for key 0x%x: memorysize too small", shm_key);
            efree(shm_list_ptr);
            RETURN_FALSE;
      }
      if ((shm_id = shmget(shm_key, shm_size, shm_flag | IPC_CREAT | IPC_EXCL)) < 0) {
            php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed for key 0x%x: %s", shm_key, strerror(errno));
             efree(shm_list_ptr);
             RETURN_FALSE;
     }
}
2004-04-24 12:31:43
http://php5.kiev.ua/manual/ru/function.shm-attach.html
Cecil, the key of a var is an integer (not the name ). You can put multiples vars in the same share.

#!/usr/local/bin/php -q
<?PHP

$SHM_KEY 
ftok(__FILE__chr) ); 

$data shm_attach($SHM_KEY10240666);

$test1 = array("hello","world","1","2","3");
$test2 = array("hello","world","4","5","6");
$test3 = array("hello","world","7","8","9");

shm_put_var($data1$test1);
shm_put_var($data2,$test2);
shm_put_var($data3,$test3);

print_r(shm_get_var($data1));
print_r(shm_get_var($data2));
print_r(shm_get_var($data3));

shm_detach($data);
?>
2005-03-28 07:17:45
http://php5.kiev.ua/manual/ru/function.shm-attach.html
If one process make a shm_attach to one inexistent memory area, this area will be created under the same priviliegies of the script running user. If another process will try to create or acces the same area, runnig by other user with different privileges of the first user, an error will occur.
2006-02-23 11:33:32
http://php5.kiev.ua/manual/ru/function.shm-attach.html
Автор:
The limit for one SHM block seems to be 32 MB, but you can split your data in several SHM blocks if you need to. The total SHM limit seems to be about 8 GB.

I'm not sure whether this is true for all configurations.
2006-11-04 17:36:36
http://php5.kiev.ua/manual/ru/function.shm-attach.html
Автор:
Since there aren't seperate functions for CREATING and ATTACHING shared memory (a mistake in my opinion), you might want to do some testing to check whether you've created it or not, as you may not want the slave of a master/slave pair to ever create the shared memory.

One way you can test this is by having your slave set the size to something small, then testing the size by putting a variable too large to fit, e.g.:

function get_shmem() {
     return shm_attach(ftok('somefile.txt', 'T'), 100, 0644);
}

$shm = get_shmem();

while (!@shm_put_var($shm, 1, str_repeat('.....', 20))) {
     shm_remove($shm); 
     sleep(1);
     //we created it, so we'll remove it and sleep to wait for the master to create it, then try again.
     $shm = get_shmem();
}
shm_remove_var($shm, 1);
//here we know the shared memory was already created, because we could put a variable in bigger than the size requested.

Another way you can handle it is to have all programs initialize the shared memory with the same parameters... I had a problem with this when my clients starting too fast and created the shmem without passing a memsize value, so it was defaulting to 10k which was too small.
2007-01-24 10:26:09
http://php5.kiev.ua/manual/ru/function.shm-attach.html
Автор:
As a follow-up to my last post regarding shm_attach and its limit capability for knowing how it was created....

for more control, use the shmop_* series of functions, as they have finer grained control than these.

and by the way:  the SHMOP functions SHOULD BE listed under "see also" for all the SHM* wrapper functions (I assume they are wrappers to the SHMOP* functions).
2007-03-08 11:08:22
http://php5.kiev.ua/manual/ru/function.shm-attach.html
I tried all the suggestions above for getting the object size (in bytes) for $memsize, but they didn't work universally for the two types of objects I tried (string and array of strings).

After doing some googling and experimenting, I've found the following magic formula:

$memsize = ( strlen( serialize( $object ) ) + 44 ) * 2;

I found this in someone else's code, so I can't explain it.
2007-08-03 18:35:46
http://php5.kiev.ua/manual/ru/function.shm-attach.html
Hi :)
I write small class for build bright message between my application.

<?
class Bright_Message
{

var 
$bright;
var 
$SHM_KEY;
var 
$my_pid;

        function 
Bright_Message($SHM_KEY=null)
        {
               
$this->my_pid getmypid();//Get own pid
               
if (is_null($SHM_KEY)) $this->SHM_KEY '123123123';
               
$this->bright shm_attach($this->SHM_KEY10240666);
               
$this->one_instance();
        }

        function 
get_msg($id,$remove=true)
        {
                if(@
$msg=shm_get_var($this->bright,$id))
                {
                   if (
$remove) @shm_remove_var($this->bright,$id);
                   return 
$msg;
                } else return 
false;
        }

        function 
snd_msg($id,$msg)
        {
                @
shm_put_var($this->bright,$id,$msg);
                return 
true;
        }

        function 
one_instance()
        {
               
$SHM_PID $this->get_msg(1,false);
                if((
strpos(exec('ps p'.$SHM_PID),$_SERVER['SCRIPT_FILENAME'])) === false)
               
$this->snd_msg(1,$this->my_pid); else
                {
                        echo 
"This program exists on pid: $SHM_PID\r\n\r\n";
                        exit;
                }
        }

}
?>

send.php:
<?
include "bridge_message.class.php";
$shm = new Bright_Message();
$shm->snd_msg(2,'this is my simple message');
?>

receive.php:
<?
include "bridge_message.class.php";
$shm = new Bright_Message();
$msg get_msg(2);
echo 
print_r($msg,1);
?>
2008-01-11 07:18:08
http://php5.kiev.ua/manual/ru/function.shm-attach.html
<?php

//how to calculate the  minimum $memsize required to store the variable $foo where $foo='foobar'.

// when shm_attach() is called for the first time, PHP writes a header to the beginning of the shared memory. 
$shmHeaderSize = (PHP_INT_SIZE 4) + 8;

// when shm_put_var() is called, the variable is serialized and a small header is placed in front of it before it is written to shared memory.
$shmVarSize = (((strlen(serialize($foo))+ (PHP_INT_SIZE)) /) * ) + 4;

// now add the two together to get the total memory required. Of course, if you are storing more than one variable then you dont need to add $shmHeaderSize for each variable, only add it once.
$memsize $shmHeaderSize $shmVarSize;

//this will give you just enough memory to store the one variable using shm_put_var().
$shm_id shm_attach $key$memsize0666 ) ;
shm_put_var  $shm_id  $variable_key  $foo  );

any attempt to store another variable will result in a 'not enough memory' error.
Be aware that if you change the contents of $foo to a larger value and then you try to write it to shared memory again using shm_put_var(), then you will get a 'not enough memory' errorIn this case, you will have to resize your shared memory segment and then write the new value.

If 
you are only storing variables that contain a single integer valuethen you can avoid having to resize by always allocating the largest amount of memory that is required to store an intwhich should be:
$shmIntVarSize = (((strlen(serialize(PHP_INT_MAX))+ (PHP_INT_SIZE)) /) * ) + 4;

?>
2008-08-14 03:19:12
http://php5.kiev.ua/manual/ru/function.shm-attach.html
Responding to jpeter1978 at yahoo dot com ... Assuming a character is typically two bytes, the size of a serialized variable (incl array or obj) is 2 * its strlen().  The 44 is 4 more than the 24 + 16 = 40 suggested by php at cytrax dot de plus 4 bytes for worst case 4-byte alignment.  So this is probably a reliable formula if you are too lazy to align it using something similar to zeppelinux at comcast dot net as in:

($strlen($serialized_array_or_obj) /4 ) * 4 ) + 40;

The zeppelinux formula would use 20 (for 4-byte integer cpu) or 36 (for 64-bit or 8-byte cpu) for the ending constant so 40 or 44 is probably just achieving header padding but it certainly can't hurt.
2008-09-18 08:31:56
http://php5.kiev.ua/manual/ru/function.shm-attach.html
A simple Sample to introduce SHM.

<?php
if ( sizeof($argv)<) {
        echo 
"Usage: $argv[0] send|recv|rem|dele ID [msg] \n\n" ;
        echo 
"   EX: $argv[0] send 1 \"This is no 1\" \n" ;
        echo 
"       $argv[0] recv 1 \n" ;
        echo 
"       $argv[0] rem 1 \n" ;
        echo 
"       $argv[0] dele \n" ;
        exit;
}

// $SHMKey = ftok(__FILE__, "Z");
$SHMKey "123456" ;

## Create/Open a shm
$seg shm_attach$SHMKey10240666 ) ;

switch ( 
$argv[1] ) {
    case 
"send":
       
shm_put_var($seg$argv[2], $argv[3]);
        echo 
"send msg done...\n" ;
        break;
       
    case 
"recv":
       
$data shm_get_var($seg$argv[2]);
        echo 
$data "\n" ;
        break;
   
    case 
"rem":
       
shm_remove_var($seg$argv[2]);
        break;

    case 
"dele":
       
shm_remove($seg);
        break;
   
    case 
"dele2":
        `
/usr/bin/ipcrm -M 123456`;
        break;
}
?>
2009-02-26 20:43:43
http://php5.kiev.ua/manual/ru/function.shm-attach.html
In my log I have found string
"shm_attach(): failed for key 0x366f: No space left on device" 
But have not found any suggestion for this at php.net and at google.

So question was how to make free memory used by shm_attach .
At first to view (Linux)  how many segments allocated, use 
:~# ipcs -mu
then
limits
:~# ipcs -ml

to remove segment use:
:~# ipcrm -m [shmid]

otherwise you can reboot server, or launch sh script based on commands above.

To avoid troubles with "No space left on device" ALWAYS use 
shm_remove() & shm_detach() after call shm_attach().
2010-08-05 06:07:09
http://php5.kiev.ua/manual/ru/function.shm-attach.html
I was playing around with these functions and made a class in the process. This will of course be slower than accessing a variable locally, but gives the ability to store variables in a shared environment and gives many running scripts the understanding that it should access them from the shared area. This should also auto destroy the shared memory area once no more scripts have a link to the data (when all scripts use this class).

<?php
class SharedMemory{
    private 
$nameToKey = array();
    private 
$key;
    private 
$id;
    function 
__construct($key null){
        if(
$key === null){
           
$tmp tempnam('/tmp''PHP');
           
$this->key ftok($tmp'a');
           
$this->id shm_attach($this->key);
           
$this->nameToKey[] = '';
           
$this->nameToKey[] = '';
           
$this->updateMemoryVarList();
           
shm_put_var($this->id11);
        }else{
           
$this->key $key;
           
$this->id sem_get($this->key);
           
$this->refreshMemoryVarList();
           
shm_put_var($this->id1shm_get_var($this->id1) + 1);
        }
        if(!
$this->id)
            die(
'Unable to create shared memory segment');
    }
    function 
__sleep(){
       
shm_detach($this->id);
    }
    function 
__destruct(){
        if(
shm_get_var($this->id1) == 1){
           
// I am the last listener so kill shared memory space
           
$this->remove();
        }else{
           
shm_detach($this->id);
           
shm_put_var($this->id1shm_get_var($this->id1) - 1);
        }
    }
    function 
__wakeup(){
       
$this->id sem_get($this->key);
       
shm_attach($this->id);
       
$this->refreshMemoryVarList();
       
shm_put_var($this->id1shm_get_var($this->id1) + 1);
    }
    function 
getKey(){
        return 
$this->key;
    }
    function 
remove(){
       
shm_remove($this->id);
    }
    function 
refreshMemoryVarList(){
       
$this->nameToKey shm_get_var($this->id0);
    }
    function 
updateMemoryVarList(){
       
shm_put_var($this->id0$this->nameToKey);
    }
    function 
__get($var){
        if(!
in_array($var$this->nameToKey)){
           
$this->refreshMemoryVarList();
        }
        return 
shm_get_var($this->idarray_search($var$this->nameToKey));
    }
    function 
__set($var$val){
        if(!
in_array($var$this->nameToKey)){
           
$this->refreshMemoryVarList();
           
$this->nameToKey[] = $var;
           
$this->updateMemoryVarList();
        }
       
shm_put_var($this->idarray_search($var$this->nameToKey), $val);
    }
}

// Example
$sharedMem = new SharedMemory();
$pid pcntl_fork();
if(
$pid){
   
//parent
   
sleep(1);
    echo 
"Parent Says: " $sharedMem->"\n";
    echo 
"Parent Changed to 0\n";
   
$sharedMem->0;
   
//Parent just changed it to 0
   
echo "Parent Says: " $sharedMem->"\n";
   
sleep(2);
   
// Parent think's it's 0, but child has changed it to 1
   
echo "Parent Says: " $sharedMem->"\n";
}else{
   
//child
   
$sharedMem->2;
    echo 
"Child Changed to 2\n";
   
// Should be 2 as child just set it to 2
   
echo "Child Says: " $sharedMem->"\n";
   
sleep(2);
   
// Child think's it's 2, but the parent set it to 0.
   
echo "Child Says: " $sharedMem->"\n";
    echo 
"Child Added 1\n";
   
$sharedMem->a++;
    echo 
"Child Says: " $sharedMem->"\n";
}
?>
2011-04-05 16:21:21
http://php5.kiev.ua/manual/ru/function.shm-attach.html
You might expect the SHM functions to be significantly faster than building variables from MySQL operations. Unfortunately this is not the case regarding large multidimensional arrays. I've tested write, read, update and delete operations with with a two dimensional associative array directly with SHM and in comparison with a class using MySQL and a class using SHMOP functions (with mostly offset-accurate serialization). Both classes generated the same array as stored with SHM. Unlike SHMOP the performance of SHM decreases considerably with larger arrays. At 2000 instructions with an $array[$row][$key] of 200 rows and 5 keys even MySql is faster than SHM.This might be due to the fact, that SHM deals with any kind of arrays and makes internal use the PHPs powerful serialize() function.
2011-10-15 20:07:05
http://php5.kiev.ua/manual/ru/function.shm-attach.html
Автор:
If you get an error like "PHP Warning:  shm_attach(): failed for key 0x61040bb5: Cannot allocate memory" then you might need to tweak your shared memory configuration.

To see your system values, enter "sysctl kern.sysv."
Important values are kern.sysv.shmmax and kern.sysv.shmall:
* kern.sysv.shmmax is the max number of bytes one shared memory segment may have
* kern.sysv.shmall is the max number of memory pages all shared memory segments together can consume
One memory page is 4096 bytes, meaning that if you set kern.sysv.shmmax to 1073741824 (1GB) then kern.sysv.shmall must be at least 262144 to be able to allocate a one GB memory segment (since 262144 * 4096 = 1073741824).

tl;dr The default values on some systems are very low and then it is not enough to only increase kern.sysv.shmmax - also kern.sysv.shmall needs to be increased accordingly!
2014-03-27 13:30:30
http://php5.kiev.ua/manual/ru/function.shm-attach.html
small shm class..
example usage:
$shx= new shmSmart;
$shx->put("key_name_apple","key_val_peach"); //set example..
$shx->put("key name alternative array",array(1=>"banana","apricot","blablabla"=>array("new-blaala"))); //set array example..
echo  $shx->get("key_name_apple"); // get example key value.
$shx->del("key_name_apple"); // delete key
unset($shx); // free memory in php..

class shmSmart{
  public $shm;            //holds shared memory resource
  public function __construct(){
    if(function_exists("shm_attach")===FALSE){
      die("\nYour PHP configuration needs adjustment. See: http://us2.php.net/manual/en/shmop.setup.php. To enable the System V shared memory support compile PHP with the option --enable-sysvshm.");
    } 
    $this->attach();    //create resources (shared memory)
  }
  public function attach(){
    $this->shm=shm_attach(0x701da13b,33554432);    //allocate shared memory
  }
  public function dettach(){
    return shm_detach($this->shm);    //allocate shared memory
  }
  public function remove(){
    return shm_remove($this->shm);    //dallocate shared memory
  }
  public function put($key,$var) {
    return shm_put_var($this->shm,$this->shm_key($key),$var);    //store var 
  }
  public function get($key){
    if($this->has($key)){
      return shm_get_var($this->shm,$this->shm_key($key));  //get var
    }else{
      return false;   
    }       
  }
  public function del($key){
    if($this->has($key)){
      return shm_remove_var($this->shm,$this->shm_key($key)); // delete var
    }else{
      return false;   
    }       
  }
  public function has($key){
    if(shm_has_var($this->shm,$this->shm_key($key))){ // check is isset
      return true;       
    }else{
      return false;       
    }
  }
  public function shm_key($val){ // enable all world langs and chars !
    return preg_replace("/[^0-9]/","",(preg_replace("/[^0-9]/","",md5($val))/35676248)/619876); // text to number system.
  }
  public function __wakeup() {
    $this->attach();
  }
  public function __destruct() {
    $this->dettach();
    unset($this);
  }   
}
2014-04-21 23:13:46
http://php5.kiev.ua/manual/ru/function.shm-attach.html
Автор:
Under the "Notes" section, it is stated that one can cast the resource ID returned by shm_attach() to an integer as of PHP 5.3.0; however, this will NOT be the same integer as the shmid value which is returned from the native SysV function shmget() on Linux (as I was hoping it might be). The integer returned by casting is merely the ID number of the resource, which is totally useless outside of the context of these functions, AFAICT.

To verify this, one can allocate a memory block with shm_attach() (or shmop_open()), print out the resource returned and compare it to the value in the "shmid" column when running "ipcs" in a terminal on Linux (or some other *nix OS).
2018-02-13 09:40:05
http://php5.kiev.ua/manual/ru/function.shm-attach.html

    Поддержать сайт на родительском проекте КГБ