PHP process and interprocess communication

environment

The process in php is completed in the form of extension. Through these extensions, we can easily complete a series of actions of the process.

pcntl extension: the main process extension, which completes the process creation in the waiting operation.
posix extension: complete the general api of posix compatible machine, such as obtaining process id, killing process, etc.
sysvmsg extension: message queue for inter process communication in system v mode.
sysvsem extension: realize the semaphore of system v mode.
sysvshm extension: realize the shared memory of system v mode.
sockets extension: realize socket communication.
These extensions can only be used in linux/mac and are not supported in window s. Finally, php version is recommended to be 5.5 +.

Simple example

A simple PHP multi process example. In this example, a child process and a parent process. The subprocess outputs 5 times and exits the program.

echo "parent progress pid:{$parentPid}\n";

$childList = array();

$pid = pcntl_fork();

if ( $pid == -1) {

    // Creation failed

    exit("fork progress error!\n");

} else if ($pid == 0) {

    // Subprocess executor

    $pid = posix_getpid();

    $repeatNum = 5;

    for ( $i = 1; $i <= $repeatNum; $i++) {

        echo "({$pid})child progress is running! {$i} \n";

        $rand = rand(1,3);

        sleep($rand);

    }

    exit("({$pid})child progress end!\n");

} else {

    // Parent process executor

    $childList[$pid] = 1;

}

// Wait for the child process to end

pcntl_wait($status);
echo "({$parentPid})main progress end!";

Perfect, finally created a child process, a parent process. Is it over? No, the processes are independent of each other and have no intersection. The scope of use is seriously affected now. What to do? It's interprocess communication.

4, Interprocess communication (IPC)

Generally, the process communication methods in linux include: message queue, semaphore, shared memory, signal, pipeline and socket.

1. Message queue
A message queue is a queue stored in memory. The following code will create three producer subprocesses and two consumer subprocesses. The five processes will communicate through message queuing.

echo "parent progress pid:{$parentPid}\n";$childList = array();
// Create message queues and define message types (similar to libraries in a database)
$id = ftok(__FILE__,'m');
$msgQueue = msg_get_queue($id);
const MSG_TYPE = 1;
// producer
function producer(){
    global $msgQueue;
    $pid = posix_getpid();
    $repeatNum = 5;
    for ( $i = 1; $i <= $repeatNum; $i++) {
        $str = "({$pid})progress create! {$i}";
        msg_send($msgQueue,MSG_TYPE,$str);
        $rand = rand(1,3);
        sleep($rand);
    }
}
// consumer
function consumer(){
    global $msgQueue;
    $pid = posix_getpid();
    $repeatNum = 6;
    for ( $i = 1; $i <= $repeatNum; $i++) {
        $rel = msg_receive($msgQueue,MSG_TYPE,$msgType,1024,$message);
        echo "{$message} | consumer({$pid}) destroy \n";
        $rand = rand(1,3);
        sleep($rand);
    }
}
function createProgress($callback){
    $pid = pcntl_fork();
    if ( $pid == -1) {
        // Creation failed
        exit("fork progress error!\n");
    } else if ($pid == 0) {
        // Subprocess executor
        $pid = posix_getpid();
        $callback();
        exit("({$pid})child progress end!\n");
    }else{
        // Parent process executor
        return $pid;
    }
}
// 3 write processes
for ($i = 0; $i < 3; $i ++ ) {
    $pid = createProgress('producer');
    $childList[$pid] = 1;
    echo "create producer child progress: {$pid} \n";
}
// 2 write processes
for ($i = 0; $i < 2; $i ++ ) {
    $pid = createProgress('consumer');
    $childList[$pid] = 1;
    echo "create consumer child progress: {$pid} \n";
}
// Wait for all child processes to finish
while(!empty($childList)){
    $childPid = pcntl_wait($status);
    if ($childPid > 0){
        unset($childList[$childPid]);
    }
}
echo "({$parentPid})main progress end!\n";

Since only one process can access the data in the message queue, no additional locks or semaphores are required.

2. Semaphores and shared memory

Semaphore: it is an atomic operation provided by the system. It is a semaphore. At the same time, only one process can operate. When a process obtains a semaphore, it must be released by the process.

Shared memory: it is a common memory area opened up by the system in the memory. Any process can access it. 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.

Next, create multiple processes to modify the same value in memory.

echo "parent progress pid:{$parentPid}\n";
$childList = array();

// Create shared memory, create semaphores, and define shared key s
$shm_id = ftok(__FILE__,'m');
$sem_id = ftok(__FILE__,'s');
$shareMemory = shm_attach($shm_id);
$signal = sem_get($sem_id);
const SHARE_KEY = 1;
// producer
function producer(){
    global $shareMemory;
    global $signal;
    $pid = posix_getpid();
    $repeatNum = 5;
    for ( $i = 1; $i <= $repeatNum; $i++) {
        // Get semaphore
        sem_acquire($signal);
        
        if (shm_has_var($shareMemory,SHARE_KEY)){
            // Value, plus one
            $count = shm_get_var($shareMemory,SHARE_KEY);
            $count ++;
            shm_put_var($shareMemory,SHARE_KEY,$count);
            echo "({$pid}) count: {$count}\n";
        }else{
            // No value, initialization
            shm_put_var($shareMemory,SHARE_KEY,0);
            echo "({$pid}) count: 0\n";
        }
        // Run out release
        sem_release($signal);
        
        $rand = rand(1,3);
        sleep($rand);
    }
}
function createProgress($callback){
    $pid = pcntl_fork();
    if ( $pid == -1) {
        // Creation failed
        exit("fork progress error!\n");
    } else if ($pid == 0) {
        // Subprocess executor
        $pid = posix_getpid();
        $callback();
        exit("({$pid})child progress end!\n");
    }else{
        // Parent process executor
        return $pid;
    }
}
// 3 write processes
for ($i = 0; $i < 3; $i ++ ) {
    $pid = createProgress('producer');
    $childList[$pid] = 1;
    echo "create producer child progress: {$pid} \n";
}
// Wait for all child processes to end
while(!empty($childList)){
    $childPid = pcntl_wait($status);
    if ($childPid > 0){
        unset($childList[$childPid]);
    }
}
// Free shared memory and semaphores
shm_remove($shareMemory);
sem_remove($signal);
echo "({$parentPid})main progress end!\n";

3. Signal

A signal is a system call. Usually, the kill command we use is to send a signal to a process. Specific signals can be checked by running kill -l in liunx/mac. In the following example, the parent process waits for 5 seconds and sends a sign signal to the child process. The sub process captures the signal and drops the signal processing function for processing.

echo "parent progress pid:{$parentPid}\n";

// Define a signal processing function
function sighandler($signo) {
    $pid = posix_getpid();
    echo "{$pid} progress,oh no ,I'm killed!\n";
    exit(1);
}

$pid = pcntl_fork();
if ( $pid == -1) {
    // Creation failed
    exit("fork progress error!\n");
} else if ($pid == 0) {
    // Subprocess executor
    // Register signal processing function
    declare(ticks=10);
    pcntl_signal(SIGINT, "sighandler");
    $pid = posix_getpid();
    while(true){
        echo "{$pid} child progress is running!\n";
        sleep(1);
    }
    exit("({$pid})child progress end!\n");
}else{
    // Parent process executor
    $childList[$pid] = 1;
    // After 5 seconds, the parent process sends a sign signal to the child process
    sleep(5);
    posix_kill($pid,SIGINT);
    sleep(5);
}
echo "({$parentPid})main progress end!\n";

4. Pipeline (famous pipeline)

Pipeline is a common means of multi process communication. Pipeline is divided into nameless pipeline and famous pipeline. Nameless pipeline can only be used for inter process communication with kinship, while famous pipeline can be used for any process on the same host. Only famous pipelines are introduced here. In the following example, the child process writes data and the parent process reads data.

$pipe_path = '/data/test.pipe';
if(!file_exists($pipe_path)){
    if(!posix_mkfifo($pipe_path,0664)){
        exit("create pipe error!");
    }
}
$pid = pcntl_fork();
if($pid == 0){
    // Subprocess, write data to the pipeline
    $file = fopen($pipe_path,'w');
    while (true){
        fwrite($file,'hello world');
        $rand = rand(1,3);
        sleep($rand);
    }
    exit('child end!');
}else{
    // Parent process, reading data from pipeline
    $file = fopen($pipe_path,'r');
    while (true){
        $rel = fread($file,20);
        echo "{$rel}\n";
        $rand = rand(1,2);
        sleep($rand);
    }
}

I hope the above contents can help you. More free PHP manufacturers PDF, PHP advanced architecture video materials, PHP wonderful articles can be searched on wechat. Attention: PHP open source community

2021 gold, silver and four major factories interview true questions collection, must see!

Four years essence PHP technical articles collation Collection - PHP framework article

Four years essence PHP technology collection - micro service architecture chapter

Four years essence PHP technology collection - distributed architecture chapter

Four years essence PHP technology collection - high concurrency scenario

Four years essence PHP technical articles collation Collection - database articles

Keywords: PHP Python Java Multithreading queue

Added by tomasd on Sun, 30 Jan 2022 18:11:11 +0200