6. Interacting with other software
Few pieces of software run in total isolation, most will talk to various other processes and programs on your system. Particularly on open source systems (where licensing is less of an issue) there is often little point re-inventing the wheel when, with minimal effort, you can simply call upon other existing software and libraries to perform tasks that are already a “solved problem”.
Although you may have come across some of these methods when programming for the web, there is generally less call for interactions when your script will execute and be gone in the blink of an eye. There are a number of different methods for invoking and interacting with other software, which we will cover below. The primary use for these methods is interacting with non-PHP software, however by virtue of the fact that these methods are language agnostic they can of course be used for communication between two or more scripts written in PHP.
6.1 Starting external processes from PHP, or “shelling out”
Before we can start talking to another process, that other process has to start running. You can of course manually start another piece software at the same time as your PHP script, but often it is useful for the PHP script itself to start the other software when it needs to. This is often referred to as “shelling out”.
There are a number functions available in PHP to achieve this, each doing it in a slightly different way:
6.2 Talking to other processes
Once we’ve got other processes up and running, PHP supports a number of ways to talk to them, which we’ll look at below. These methods mainly apply to processes that have been started up by other means, or which your script has started and disassociated itself from. If you’ve used popen() or proc_open() to run them, you can simply communicate via PHP streams as normal. You can still use the methods below as well though, if you need additional channels of communication.
6.3 Semaphores
6.4 Shared Memory
“Shared Memory” is a simple and widely supported method of passing data between two or more processes, and it really is as simple as it sounds. A process can create a segment of memory, with a key as a unique ID, assign standard Unix type permissions to it, and then it and other processes can read, write and delete data from that segment as necessary (and as permissions allow).
Shared memory is probably the fastest way of sharing information between two processes. There is no disk IO or database access for instance to slow you down, and no intermediate message broker to spend time processing and distributing the information. The downside is that you have to manage the whole process yourself, although this isn’t as hard as it sounds.
Shared memory is supported in two extensions, the SystemV sysvshm extension (part of the Semaphore extension like sysvsem described in the previous section) and the more recent shmop extension. We will look at the latter as it is based on the C shm api which makes it easier to share data with non-PHP programs, unlike the former which used its own proprietary data format making it hard to share with anything other than PHP. Shmop is also usually faster than the sysvshm as it stores its data in a raw form.
Like files, shared memory can become corrupt if multiple processes try to write to it at the same time. For our example below, we don’t need to worry about locking the shared memory segment as only one process will be writing to it so we won’t include any locking code for brevity and clarity. However where locking is an issue, you can use the semaphore method outlined in the previous section to ensure only one process writes to the memory segment at a time. Using multiple memory segments at the same time by the same or different processes doesn’t require locking, as long as only one process is writing to a specific segment at a given time.
It’s time to look at an example of shared memory in action. Below are two scripts. The first script below, generator.php, generates an array of three random numbers every second, encodes them as JSON and puts them into a shared memory segment. The second script, display.php, retrieves that data and outputs it to the terminal. To try these, open two terminal windows and run one in each, at the same time.
6.5 PHP message queues
Message queues provide an easy way for multiple processes to interact. At its most simple, one process adds messages to the queue, and another takes them off. The queue is maintained usually by a intermediate process or the OS itself. Queues make a programmers life easier than, say, messaging using shared memory as the programmer doesn’t need to worry (too much) about timing and synchronisation, and there are usually no need for locks. The sending process can fire off a message and forget about it (if it wants to), the receiving process can simply sit around and wait for a message to arrive (or do other things and check back for the messages later). There are a number of message queue APIs and extensions available to PHP, and we will look at most of those later in this chapter. In this section, we will look at the sysvmsg message queue which is part of the Semaphore extension that we looked at in the previous sections. This is a basic but useful message queue system, and has the advantage that it is usually compiled into most PHP distributions and it doesn’t require any third party APIs, daemons or libraries.
Lets jump right in with an example. We’re going to modify our random number generator scripts from the previous section to use a message queue. Our first script, generator2.php is going to fire off 20 messages, each with 3 random numbers, in quick succession and then exit. Our second script, display2.php, will pull those messages out at its own pace (1 per second) and display them.