English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Comunicazione tra semafori e memoria condivisa di base tra processi PHP

Poiché non è determinato chi esegue per primo tra i processi, dipende dall'algoritmo di pianificazione dei processi del kernel, che è piuttosto complesso. Di conseguenza, è possibile che più processi accedano contemporaneamente alla memoria condivisa, causando errori imprevisti. Il nome 'segnale' sembra misterioso, ma guardando il suo significato inglese, è molto facile capirlo.

semaphore [ˈseməfɔ:(r)] vt. emettere segnale, fare segno;

Simile al ruolo di un comandante.

Ora vediamo l'uso del segnale pseudo-codice.

1、Crea l'identificatore unico del segnale

$ftok = ftok(__FILE__, 'a');

2、Crea l'ID della risorsa di segnale

$sem_resouce_id = sem_get($ftok);

3、Accetta il segnale

sem_acqure($sem_resource_id);

4、Rilascia il segnale

sem_release($sem_resource_id);

5、Distruggi il segnale

sem_remove($sem_resource_id);

Facciamo un esempio non elegante per farci capire l'uso della coda di segnali nella vita quotidiana. Dopo aver capito, possiamo applicarlo al nostro campo di programmazione.
In una compagnia c'è solo un bagno. Quindi quando qualcuno usa il bagno, devono ottenere una chiave di lucchetto (segnalatore) per indicare che il bagno è in uso. Il codice è il seguente:

sem_acqure($sem_resource_id);

Dopo che l'operatore ha finito di usare il bagno, è necessario aprire il lucchetto e rilasciare il lucchetto (segnalatore), indicando che ora è possibile permettere a qualcun altro di usarlo. Il codice è il seguente:

sem_release($sem_resource_id);

Con un semplice lucchetto, possiamo sapere se il bagno (memoria condivisa) è disponibile. Questo esempio non è elegante, ma spiega il problema. Questo blog ha anche un sapore, non è facile......Di seguito è riportato il codice di esempio:

<?php
//crea area di memoria condivisa
$shm_key = ftok(__FILE__, 'a');
$shm_id = shm_attach($shm_key, 1024, 0755);
//var_dump($shm_id);die(); risorsa (4) di tipo (sysvshm)
const SHARE_KEY = 1;
$child_list = [];
//aggiungi segnalatore
$sem_id = ftok(__FILE__, 'b');
$signal = sem_get($sem_id);
//risorsa di segnale (5) di tipo (sysvsem)
for ($i = 0; $i < 3; $i++) {
  $pid = pcntl_fork();
  exit("Fallo di fork!".PHP_EOL);
    elseif ($pid == 0) {
  }
    //Ottieni il semaforo
    sem_acquire($signal);
    if (shm_has_var($shm_id,SHARE_KEY)) {
      $count = shm_get_var($shm_id, SHARE_KEY);
      $count++;
      //Simulazione di elaborazione aziendale
      $sec = rand(1, 3);
      sleep($sec);
      shm_put_var($shm_id, SHARE_KEY, $count);
    }
      $count = 0;
      $sec = rand(1, 3);
      sleep($sec);
      shm_put_var($shm_id, SHARE_KEY, $count);
    }
    echo "processo figlio: ".getmypid()." sta scrivendo! Ora count è: $count ".PHP_EOL;
    //Rilascia il semaforo
    sem_release($signal);
    exit("processo figlio".getmypid()."fine".PHP_EOL);
  }
    $child_list[] = $pid;
  }
}
while (count($child_list) > 0) {
  foreach ($child_list as $key => $pid) {
    $status = pcntl_waitpid($pid, $status);
    if ($status > 0 || $status == -1) {
      unset($child_list[$key]);
    }
  }
  sleep(1);
}
$count = shm_get_var($shm_id, SHARE_KEY);
echo " $count  ".PHP_EOL;
//Distruggi il semaforo
sem_remove($signal);
shm_remove($shm_id);
shm_detach($shm_id);
Ti potrebbe interessare