Communication between processes in PHP
PHP has several features that allow different PHP processes communicate with each other but most programmers use unknown. The paper explores how to use shared memory and semaphores from PHP and a new world of possibilities becomes reality.
Communication between processes in PHP
"Preoptimization is the root of all evil (Donald Knuth)"
In this article we will explain how to handle shared memory and semaphores from PHP, it is necessary to have php compiled with the following options:
The two extensions that we use are the extension of shared memory and semaphore extension, we aver that we do with each of them then ..
What is IPC?
IPC (Inter-process communication) mechanism is a standard Unix processes to communicate with each other. Processes residing, it's clarification, all on the same machine. Basically IPC defines 3 different forms of communication: message queues, shared memory segments and semaphores. In this article we will discuss the use of semaphores and shared memory.
Using Shared Memory from PHP
The use of shared memory segments is a very good way of communicating processes together. Basically a segment of memory that can be shared by multiple processes, if a process writes to the segment the other processes can see this data is defined. In PHP we can control with this technique the number of running, or put data in memorua preventing other processes have to generate the same information that was already generated by other processes processes. In critical applications using cache memory as a temporary storage is largely more efficient than using a file-system file
To create a shared memory segment use:
Shmop_open shm_id = $ ($ key, $ mode, $ perm, $ size);
- $ Key is the number that idnetifica the shared memory segment, all processes that want to access this same segment must know this number as a key to access the segment.
- $ Mode is the mode of creation, "c" is used to create a segment while "a" is used to access a segment already created
- $ Perm defines the permissions of the segment according to the mechanism of Unix permissions
- $ Size The size of the segment defined
The function returns an id that debermos used to read / write to the segment. It is similar to a file handle as the functions that are used to manipulate shared memory are different.
$ Shm_id = shmop_open (0xff3, "c", 0644, 100);
In the example we create a shared memory segment of 100 bytes.
If we want to access an existing use shmop_open segment by setting to 0 the third and fourth function parameters. If you want to create or access a corresponding segment according proceed as if we were creating it, if the segment already exists simply access the same.
What did we do?
There are some Unix utilities that can be called from the command line to monitor and control IPC resources, for example we use "ipcs" to check what resources are created and some of the same parameters.
------ Shared Memory Segments -------- key shmid owner perms bytes nattch status0x00280267 0 root 644 1 1048576 30x00000000 nobody dest0x00000000 600 46084 10 2 600 46084 8 dest0x00000ff3 nobody nobody 131 644 100 0 ------ Semaphore Arrays -------- key semid owner perms root nsems status0x00280269 0 666 14 ------ Message Queues -------- key msqid owner perms used-bytes messages
As we can see we have 4 shared memory segments created, the latter with (key 0x0000ff3) is that we believe in our example. We can view the properties of the segments, as the creator, permissions, size and number of processes that are using the segment in the output of ipcs command.
Returning to PHP
If we remove a shared memory segment we can use the following instruction from PHP:
shmop_delete ($ id);
The $ id we use is that the function shmop_open promptly returned it to create or access the segment.
If we remove the segment from the command line you can use the 'ipcrm shmid' eg 'ipcrm 131' command (in our example) would eliminate the segment created from PHP.
WARNING: If you use ipcrm as "root" must be very careful checking that the segment segment that will be really clear that we want to eliminate. If we remove other segments belonging to other processes we can produce unexpected results and generally are pretty bad ...
Reading and writing data
To write data to a shared memory segment use:
shmop_write int (int shmid, string data, int offset)
shmid is the id that remanded shmop_open, data is data (what else?) and the offset is the offset within the segment (0 to start writing at the beginning of it)
To read use:
shmop_read string (shmid int, int start, int count)
We indicate the position (offset) from which we read (0 for the start of the segment) and the number of bytes to read. Using shared memory data does not have any meaning beyond being strips of bytes, in most implementations is good to build classes that handle shared memory taking charge of providing interfaces for guaradar strings, objects and other data types. The class is then responsible for handling lengths and to abstract the concept of strip bytes in memory programmer.
We will not have any problems creating, accessing, reading and writing a shared memory segment from a single isolated process. But we can find some problems when more than one process at the same time try to use the segment, we are about to enter the fascinating world of concurrent processes and the problem of mutual exclusion.
Suppose we have two processes reading and writing data to a single shared memory segment. If two processes try to write data to the same position in memory at the same time can get inconsistencies, this is known as the "problem of mutual exclusion" There is a lot of information and literature on the subject mainly in books on operating systems. A simple way to achieve mutual exclusion semaphores is using, and is the mechanism we will study below.
The semaphores are another IPC resources, we can see information about the system semaphores with ipcs and remove ipcrm. To create a semaphore from Php to use:
sem_get int (int key, int [max_acquire [, int perm]])
The semaphore is created if needed or accessed if already existed. The function returns a handle that is used to manipulate the semaphore. max_acquiere indicates the maximum number of processes that can acquire the semaphore without releasing it, the default is 1 Permissions setean as constumbre.
Once we have the semaphore we can do with two things: acquire and release. When we acquire a semaphore might think we are increasing and if we try to increase it beyond the amount set will max_acquire process to be blocked until another process releases the semaphore lock and enable the process to buy. In binary semaphores, the most common in 90 \% of cases only one process can acquire the semaphore, other processes that want to acquire the semaphore will remain blocked until the process holding the semaphore releases it.
To acquire and release semaphores use:
sem_acquire int (int sem_identifier)
sem_release int (int sem_identifier)
Where is the identifier we obtained with sem_get
A simple protocol for mutual exclusion.
We can use the following protocol to achieve mutual exclusion from PHP:
$ Semid = sem_get (0xee3,1,0666) = $ shm_id shmop_open (0xff3, "c", 0644, 100); sem_acquire ($ semid); / * If we are here we are alone! * / WRITE TO THE SHARED SEGMENT HEREsem_release ($ semid);
As we can see the mechanism is simple, the semaphore is acquired, does something and then the semaphore is released. We can be sure that it is impossible for two processes simultaneously writing this because once one acquires the semaphore others are blocked until the semaphore is released. The lines between sem_release sem_acquire and are known as "critical section", ie areas where we do not want two processes simultaneously attend.
An interesting comment is that in PHP semaphore implementation process that releases the semaphore should be the same as acquired. A process can not release a semaphore acquired by another process. This is not common in other languages that use IPC so we must take this into account.
Importantly, we only have to worry about mutual exclusion between writers who read more than one process the same shared memory segment at a time no problem but if there is any process "writer" then the process should be the one to access memory. This is a known concurrency problem known as the problem of readers-writers.
There are several applications for IPC, for some simple optimization recursoso as stored in shared memory configuration files parsed to advanced search engines, or systems authentication cache.