PHP Dark Arts: Shared Memory Segments (IPC)

Note: The full source code for the examples can be downloaded here.

In my previous articles on using PHP for multi-process programming, we kept it very simple.  By simple, I mean we didn’t have any inter-process communication (IPC).  IPC is a set of techniques for the exchange of data amongst separate processes and/or threads.  There are many different ways to set up IPC, such as files, signals, sockets, pipes, semaphores, shared memory, and message passing.  This time around, we’re going to cover PHP’s implementation of shared memory segments.

So what does it mean to share a memory segment?  It means that the program will create a section of memory that can be accessed by other processes on the system.  Normally this isn’t the case, since most processes have mutually exclusive address spaces.  The benefit of using a shared memory segment is that communication between processes is extremely fast.  The main downside is that processes must be running on the same machine (and same processor in some cases), where as other types of IPC can be used over a network.

Creating a Shared Memory Segment

In order to share memory between processes, you first need to create the shared memory segment.  This is accomplished with PHP’s shm_attach() function.  The shm_attach() function takes 3 parameters.

  • $key (int) – This is an integer value that identifies your shared memory segment.  If you used 123456 for this value in one process, you would need to use the same key in another process to access the shared memory segment.
  • $memsize (int) –  This is the amount of memory (in bytes) you would like to share.  Deciding how large this should be is sort of a pain.  The easiest way it to simply pick an arbitrary amount and make sure anything you try to share isn’t larger then that.  The best way would be to know the maximum size of data you will need to share and set it to that value.
  • $perm (int) – The permissions for the shared memory segment.  These permissions follow typical Unix style permissions.  The default is 0666 which means that everyone can read from and write to this memory segment.

On success, shm_attach() returns an identifier of the shared memory segment.

1
2
3
4
5
6
7
//Define shared memory segment properties.
$key = "987654";
$permissions = 0666;
$size = 1024;
 
//Create or open the shared memory segment.
$segment = shm_attach($key, $size, $permissions);

Using Your Shared Memory Segment

Now that you have created a shared memory segment, you’ll obviously want to try it out.  Using it is pretty straight forward with the shm_put_var() and shm_get_var() functions.  They work as you might expect them to.  shm_put_var() has 3 parameters:

  • The shared memory segment key.
  • An integer used basically as an index on the data (making it easier to retrieve).
  • Some variable.  This can be anything so long as it’s smaller than the size you’ve defined the memory segment to be.

The shm_get_var() function is very similar.  It only takes 2 parameters, one of which is the key for the shared memory segment, and the other is the integer value (index) associated with the stored data.  Now that you know what the functions do, let’s put it all together in a little program.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php
//Check the command line arguments
if(sizeof($argv) < 2) {
     echo  "Usage: php shared_memory.php <send|get|delete> <integer identifier> <value>\n";
     exit;
}
 
//Define shared memory segment properties.
$key = "987654";
$permissions = 0666;
$size = 1024;
 
//Create or open the shared memory segment.
$segment = shm_attach($key, $size, $permissions);
 
//Handle operations for the segment.
switch($argv[1]) {
     case "send":
          shm_put_var($segment, $argv[2], $argv[3]);
          echo "Message sent to shared memory segment.\n";
          break;
     case "get":
          $data = shm_get_var($segment, $argv[2]);
          echo "Received data: {$data}\n";
          break;
     case "delete":
          shm_remove($segment);
          echo "Shared memory segment released.\n";
          break;
}
?>

A quick glance at the code reveals that I’m making this program a little interactive for easier use.  All it does is check to make sure your command line arguments are correct, creates / opens the shared memory segment, and then performs the given operation on the segment.  An example:

<->php shared_memory.php
Usage: php shared_memory.php send|get|delete integer identifier value;
<->php shared_memory.php send 1 "Hello.  This is the shared memory segment."
Message sent to shared memory segment.
<->php shared_memory.php get 1
Received data: Hello.  This is the shared memory segment.
<->php shared_memory.php delete
Shared memory segment content deleted.

You’ll also notice that at the end I delete the contents of the shared memory segment.  It’s important to understand the difference between detaching and deleting(removing) here.  When you detach the shared memory segment, it’s possible for your data to still exist in memory until it’s overwritten by something else.  This poses a big security threat, so you should always delete(remove) the data first.  So how do we release the memory?  By using the shm_detach() function.

<->
//Define shared memory segment properties.
$key = “987654”;
$permissions = 0666;
$size = 1024;

//Create or open the shared memory segment.
$segment = shm_attach($key, $size, $permissions);

//Detach the memory segment.
shm_detach($segment);

Download

Now that your done, check out the full source code for the examples here.  In the near future I hope to have a virtual machine available for download, so users who don’t want to mess with configuration can just start it up and go.