Categories
PHP Programming

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.

By Jack Slingerland

Founder of Kernl.us. Working and living in Raleigh, NC. I manage a team of software engineers and work in Python, Django, TypeScript, Node.js, React+Redux, Angular, and PHP. I enjoy hanging out with my wife and son, lifting weights, and advancing Kernl.us in my free time.

16 replies on “PHP Dark Arts: Shared Memory Segments (IPC)”

This is a really good question that I sadly don’t have a great answer for. Looking through the PHP documentation, there really isn’t anything said about collision with other programs. I’m not sure, but I think the memory segment is actually managed by the underlying OS, and the key is just an internal device used by PHP to make finding the starting address of the memory segment easier. Something like {code type=php}$key_array[12345] = “0x56324526”;{/code} Sorry I couldn’t be of more help, but do let me know if you find the answer to this!

The function you are talking about is called “ftok()” which is intended to help reduce collisions but apparently is prone to collisions still due to its inner workings. The “fileinode()” function seems to be a decent alternative however 🙂

Deepak, why do you want to store database connection descriptor in ram? You ALWAYS need to create/open new database connection descriptor for every single http request.

Though are many ways to avoid expensive database connection time, it is not easy to post here 🙂

However you should learn following areas in PHP:
Socket Programming
Signals handling
Process handling

Hello. Great article. Can you give me an example of a practical use for this. I understand what you have said, but can’t see how this would be used. Thanks.

Shared memory segments are often used in multi-process programs to share information. For instance, let’s say your main process forked a new process to FTP a file to a server. While the child process is uploading the file, the main process wants status updates. Using the shared memory segment, the child process can keep the parent process up to date. Most status bars in desktop programs work in a manner similar to this.

Nice post, but not good for websites, will slow down the site response. Better create a daemon and access it through socket call inside your php web scripts. Socket call would take 2ms, daemon would take minimum 4 micro seconds.

You can also use /dev/shm ram disk directly. easy to use and faster than shm.

Comments are closed.