Communication between processes in PHP
PHP has several features that allow different PHP processes communicate with each other but most programmers know how to use. The paper explores how to use shared memory and semaphores from PHP and a new world of possibilities is realized.
Communication between processes in PHP
"Preoptimization is the root of all evil (Donald Knuth)"
In this article we will explain how to manage shared memory and semaphores from PHP, to do this you need 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) is a standard Unix mechanism for 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 it defines a segment of memory that can be shared by several processes, if a process writes to the segment the other processes can see this data. In PHP with this technique we can control the number of processes running, or put data in memorua preventing other processes have to generate the same information that was already generated by other processes. In critical applications using cache memory as a temporary storage medium is largely more efficient than using a file-system file
To create a shared memory segment used:
$ Shm_id = shmop_open ($ key, $ mode, $ perm, $ size);
- $ Key is the number that idnetifica 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 segment defines the permissions according to Unix permissions mechanism
- $ Size sets the segment size as ~ o
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 segment shmop_open use by setting to 0 the third and fourth parameters of the function. If you want to create or access a second segment corresponds 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 can use "ipcs" to check that resources are created and some parameters of the same.
------ Shared Memory Segments -------- key owner perms bytes nattch shmid status0x00280267 0 30x00000000 1 root nobody 644 1048576 600 46084 10 46084 600 dest0x00000000 February 8 dest0x00000ff3 nobody nobody 131 644 100 0 ------ Semaphore Arrays -------- key semid owner perms nsems status0x00280269 0 666 root 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 see the properties of the segments, as the creator, permissions, size and number of processes that are using the segment ipcs command output.
Returning to PHP
If we remove a shared memory segment can use the following instruction from PHP:
shmop_delete ($ id);
The $ id that we use is promptly returned it shmop_open function to create or access the segment.
If we remove the segment from the command line, use the command "ipcrm shmid 'for example' ipcrm 131 '(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 we will delete it really what we want to eliminate. If we remove other segments belonging to other processes can produce unexpected results and generally are pretty bad ...
Reading and writing data
To write data to a shared memory segment used:
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)
Used for reading:
shmop_read string (shmid int, int start, int count)
We indicate the position (offset) from which we read (0 for the beginning of the segment) and the number of bytes to read. Using shared memory data does not have any meaning beyond to be strips of bytes, in most implementations is good to build classes that handle shared memory taking charge of providing interfaces for guaradar strings, objects or other types of data. The class is then responsible for handling the 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 we can get inconsistencies, this is known as the "mutual exclusion problem" there is a lot of information and literature on the subject mainly in books on operating systems. A simple way to achieve mutual exclusion is using semaphores, 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 them with ipcrm. To create a semaphore from Php is used:
sem_get int (int key [, int max_acquire [, int perm]])
The semaphore is created if necessary or if it already existed accessed. 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. Permits as constumbre setean.
Once we have the semaphore can do two things with it: acquire and release. When we acquire a traffic light we think that we are increasing and if we try to increase it beyond the amount seteada with max_acquire the process is blocked until another process releases the semaphore and enable the blocked process to buy. In binary semaphores, the most common in the 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 identifier is the we got with sem_get
A simple protocol for mutual exclusion.
We 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, it acquires the semaphore, you do something and then releases the semaphore. We can be sure that it is impossible that two processes are writing at the same time 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 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, but a process that read the same shared memory segment at a time no problem but if there is a process "writer" then the process should be the one to memory accesses. This is a known concurrency problem known as the problem of readers-writers.
There are several applications for IPC, from some simple recursoso optimization in shared memory as saving configuration files parsed to advanced search engines, or cache authentication systems.