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

Básico de Comunicação de Processos em PHP: Semáforos e Comunicação de Memória Compartilhada

Devido ao fato de que a ordem de execução entre processos não é determinada, depende da algoritmo de escalonamento de processos do núcleo, que é complexo. Portanto, pode haver múltiplos processos acessando a memória compartilhada ao mesmo tempo, causando erros imprevisíveis. O nome 'semaforo' é misterioso, mas sua significação em inglês é fácil de entender.

semaphore 英[ˈseməfɔ:(r)] vt. Emitir sinal, sinalizar;

Semelhante ao papel de um comandante.

Vamos ver o uso de um sinal de código falso a seguir.

1Criar identificador único de semáforo

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

2Criar ID de recurso de semáforo

$sem_resouce_id = sem_get($ftok);

3Aceitar semáforo

sem_acqure($sem_resource_id);

4Liberar semáforo

sem_release($sem_resource_id);

5Destruir semáforo

sem_remove($sem_resource_id);

Vamos dar um exemplo impuro para facilitar a compreensão da utilização da variável de sinal na vida real. Após compreender, podemos aplicá-la ao nosso campo de programação.
Uma empresa tem apenas um banheiro. Portanto, quando alguém usar o banheiro, é necessário obter uma chave de bloqueio (semaforo) para indicar que o banheiro está em uso. O código é o seguinte:

sem_acqure($sem_resource_id);

Depois que os funcionários terminarem de usar o banheiro, é necessário abrir o bloqueio, liberar o bloqueio (semaforo), indicando que agora pode permitir que outros o usem. O código é o seguinte:

sem_release($sem_resource_id);

Através de um simples bloqueio, podemos saber se o banheiro (memória compartilhada) está disponível. Este exemplo é pouco apropriado, mas ilustra o problema. Este blog também tem um sabor peculiar, é difícil de descrever。。。。A seguir está o código de exemplo:

<?php
//Criar área de memória compartilhada
$shm_key = ftok(__FILE__, 'a');
$shm_id = shm_attach($shm_key, 1024, 0755);
//var_dump($shm_id);die(); resource(4) of type (sysvshm)
const SHARE_KEY = 1;
$child_list = [];
//Adicionar semáforo
$sem_id = ftok(__FILE__, 'b');
$signal = sem_get($sem_id);
//$signal resource(5) of type (sysvsem)
for ($i = 0; $i < 3; $i++) {
  $pid = pcntl_fork();
  if ($pid == -1) {
    exit("Falha de bifurcação!".PHP_EOL);
  } elseif ($pid == 0) {
    //Obter sinal
    sem_acquire($signal);
    if (shm_has_var($shm_id,SHARE_KEY)) {
      $count = shm_get_var($shm_id, SHARE_KEY);
      $count++;
      //Simulação de processamento de negócios
      $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 filho: ".getmypid()." está escrevendo! agora o contador é: $count ".PHP_EOL;
    //Liberar sinal
    sem_release($signal);
    exit("processo filho".getmypid()."final".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;
//Destruir sinal
sem_remove($signal);
shm_remove($shm_id);
shm_detach($shm_id);
Você Também Pode Gostar