php interprocess communication semaphores and shared memory

Keywords: PHP REST Programming Unix

Why interprocess communication is needed

When a process accesses critical resources, it is possible for multiple processes to access critical resources at the same time in the same time, resulting in unexpected errors due to the uncertainty of who executes first between processes (which depends on the process scheduling algorithm of the kernel, which is more complex).

Critical resources
Critical resources refer to some shared resources which are shared resources but cannot be accessed by multiple processes at the same time. When a process is using critical resources, other processes must wait for the consuming process to release the shared resources according to the synchronization mechanism of the operating system before competing for the shared resources again.

Shared memory
Shared memory is a common memory area opened by the system in memory, which can be accessed by any process. At the same time, multiple processes can access the area. In order to ensure the consistency of data, it is necessary to lock or semaphore the memory area.

Semaphore
The name semaphore is puzzling, but it's easy to understand from its original English meaning.
semaphore English [ˈ sem ə f ɔ: (r)] vt;
Similar to the role of a commander.
For example, chestnuts make it easy to understand the use of this semaphore in life. After understanding, it can be applied to our programming field.
A company has only one bathroom. So when someone goes to the toilet, they need to get a flag (semaphore) and put it in the chrysanthemum at the door of the toilet to show that the toilet is in use. After the employees go to the toilet, they need to pull out the flag and release it (semaphore), indicating that they can be used by others now. Through a simple action of inserting and inserting flags, we can know whether the current toilet (shared memory) can be used.

Classic question - philosophers eat
There are five philosophers who eat at a table. Each philosopher has two pairs of chopsticks in front of him. Only when he has two pairs of chopsticks on his left and right can he eat. In this case, there is an extreme scenario where five philosophers pick up the chopsticks on the left hand side at the same time. When they continue to take the chopsticks on the right hand side, they find that they have been taken by the philosophers on the left hand. This led to an embarrassing situation. Five philosophers had chopsticks in their left hand and their right hand was empty. They fell into a dead cycle of waiting for chopsticks on the right side. Finally, five philosophers starved to death......
Solution: very simple, as long as five philosophers communicate with each other, semaphore means that I want to eat with chopsticks, you put the chopsticks I need first and don't move, and when my flag is down, it means that I've finished eating, you wait for me to put the chopsticks down and then go to get the chopsticks.

Demo code

Unused semaphores, shared memory for multiprocess operations

<?php
$shm_key = ftok(__FILE__,'a');//Create shared memory unique identifier
$shm_id = shm_attach($shm_key,1024,0755);//Create or open a shared memory segment

$childList = [];
const SHARE_KEY = 1;
for ($i = 0;$i < 10;$i++){
    $pid = pcntl_fork();
    if ($pid == -1){
        // Create failure
        exit("fork fail!".PHP_EOL);
    }elseif ($pid == 0){
        // Subprocess executor
        sleep(rand(1,10));
        if (shm_has_var($shm_id,SHARE_KEY)){
            $value = shm_get_var($shm_id,SHARE_KEY);
            $value++;
            //Simulated salesman processing time
            sleep(rand(1,10));
            shm_put_var($shm_id,SHARE_KEY,$value);
        }else{
            $value = 0;
            shm_put_var($shm_id,SHARE_KEY,$value);
        }
        $pid = posix_getpid();
        echo "Process:{$pid},put value is {$value}\n";
        exit("child process {$pid} exit!\n");
    }else{
        // Parent process executor
        $childList[$pid] = 1;
    }

}
//Recycle subprocesses, all system resources used by subprocesses will be released
while (!empty($childList)){
    $pid = pcntl_wait($status);
    if ($pid > 0 ){
        unset($childList[$pid]);
    }
}
echo "It's over.\n";
shm_remove($shm_id);//Remove shared memory from Unix system
shm_detach($shm_id);//Disconnect from shared memory segment

After fork 10 processes, each process will sleep(rand(1,10)), and then start to take out the value from the shared memory, accumulate 1, and save it to the shared memory. In the case of no semaphore, the actual result is messy, and the shared memory between processes is occupied and then operated.

Use semaphore, multi process operation share memory

<?php
$shm_key = ftok(__FILE__,'a');
$shm_id = shm_attach($shm_key,1024,0755);

//Add semaphore
$sem_id = ftok(__FILE__, 'b');
$signal = sem_get($sem_id);
$childList = [];
const SHARE_KEY = 1;
for ($i = 0;$i < 10;$i++){
    $pid = pcntl_fork();
    if ($pid == -1){
        exit("fork fail!".PHP_EOL);
    }elseif ($pid == 0){
        sem_acquire($signal);
        sleep(rand(1,10));
        if (shm_has_var($shm_id,SHARE_KEY)){
            $value = shm_get_var($shm_id,SHARE_KEY);
            $value++;
            //Simulated salesman processing time
            sleep(rand(1,10));
            shm_put_var($shm_id,SHARE_KEY,$value);
        }else{
            $value = 0;
            shm_put_var($shm_id,SHARE_KEY,$value);
        }
        $pid = posix_getpid();
        echo "Process:{$pid},put value is {$value}\n";
        sem_release($signal);
        exit("child process {$pid} exit!\n");
    }else{
        //Parent process
        $childList[$pid] = 1;
    }

}
//Recycle subprocesses. All system resources used by subprocesses will be released
while (!empty($childList)){
    $pid = pcntl_wait($status);
    if ($pid > 0 ){
        unset($childList[$pid]);
    }
}
echo "It's over.\n";
sem_remove($signal);
shm_remove($shm_id);
shm_detach($shm_id);

When a process has semaphores, the rest of the processes wait for the semaphores to be released, and then the rest of the processes preempt the semaphores. The shared memory of multi process operations becomes orderly. The code runs as follows

Posted by oh_maestro on Thu, 07 Nov 2019 00:22:33 -0800