You want a chunk of data to be available to all server processes through shared memory.
If you want to share data with other processes as well, use the pc_Shm class shown in Example 11-2.
For example, to store a string in shared memory, use the pc_Shm::write() method, which accepts a key, a length, and a value:
1 2 3 |
$shm = new pc_Shm(); $secret_code = 'land shark'; $shm->write('mysecret', strlen($secret_code), $secret_code); |
The pc_Shm class is shown in Example 11-2.
Example 11-2. Storing arbitrary data in shared memory
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
class pc_Shm { protected $tmp; public function __construct($tmp = '') { if (!function_exists('shmop_open')) { trigger_error('pc_Shm: shmop extension is required.', E_USER_ERROR); return; } if ($tmp != '' && is_dir($tmp) && is_writable($tmp)) { $this->tmp = $tmp; } else { $this->tmp = '/tmp'; } } public function read($id, $size) { $shm = $this->open($id, $size); $data = shmop_read($shm, 0, $size); $this->close($shm); if (!$data) { trigger_error('pc_Shm: could not read from shared memory block', E_USER_ERROR); return false; } return $data; } public function write($id, $size, $data) { $shm = $this->open($id, $size); $written = shmop_write($shm, $data, 0); $this->close($shm); if ($written != strlen($data)) { trigger_error('pc_Shm: could not write entire length of data', E_USER_ERROR); return false; } return true; } public function delete($id, $size) { $shm = $this->open($id, $size); if (shmop_delete($shm)) { $keyfile = $this->getKeyFile($id); if (file_exists($keyfile)) { unlink($keyfile); } } return true; } protected function open($id, $size) { $key = $this->getKey($id); $shm = shmop_open($key, 'c', 0644, $size); if (!$shm) { trigger_error('pc_Shm: could not create shared memory segment', E_USER_ERROR); return false; } return $shm; } protected function close($shm) { return shmop_close($shm); } protected function getKey($id) { $keyfile = $this->getKeyFile($id); if (! file_exists($keyfile)) { touch($keyfile); } return ftok($keyfile, 'R'); } protected function getKeyFile($id) { return $this->tmp . DIRECTORY_SEPARATOR . 'pcshm_' . $id; } } |
Because pc_Shm uses standard system functions for accessing shared memory, other programs (no matter what language they’re written in) can access that data as well.
For example, Example 11-3 shows a short C program that can read data written by pc_Shm.
Example 11-3. Reading shared memory data from C
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 |
#include <sys/ipc.h> #include <sys/shm.h> #include <stdio.h> int main(int argc, char **argv) { char *id; size_t size; if (argc != 3) { fprintf(stderr, "Usage: %s ID SIZE\n", argv[0]); return -1; } id = argv[1]; size = atoi(argv[2]); char *path; asprintf(&path, "/tmp/pcshm_%s", id); key_t token = ftok(path, (int) 'R'); int shmid = shmget(token, size, 0); void *ptr = shmat(shmid, 0, SHM_RDONLY); printf("%*s\n", (int) size, (char *) ptr); shmdt(ptr); free(path); } |
Compiling that program and then invoking it with arguments mysecret and 10 (or any sufficiently long length) will print the data inserted into shared memory by the PHP code.
It’s important to remember that, unlike setting a key/value pair in a regular PHP array, the shmop functions need to allocate a specific amount of space that the data stored there is expected to consume.
That is why the read and write operations require a size to be passed to them.