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

Base de comunicación de procesos en PHP: comunicación de semáforos y memoria compartida

Dado que no se sabe quién ejecutará primero entre los procesos, esto depende del algoritmo de planificación de procesos del núcleo, que es bastante complejo. Por lo tanto, es posible que varios procesos accedan simultáneamente a la memoria compartida en el mismo tiempo, causando errores imprevistos. El nombre de semáforo es bastante misterioso, pero su significado en inglés es bastante fácil de entender.

semaphore 英[ˈseməfɔ:(r)] vt. enviar una señal, hacer señales;

Es similar al papel de un comandante.

Vamos a ver el siguiente código de pseudo de uso del semáforo.

1、crear el identificador único del semáforo

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

2、crear el ID de recurso de semáforo

$sem_resouce_id = sem_get($ftok);

3、aceptar el semáforo

sem_acqure($sem_resource_id);

4、liberar el semáforo

sem_release($sem_resource_id);

5、destruir el semáforo

sem_remove($sem_resource_id);

Vamos a tomar un ejemplo poco decoroso para que sea más fácil entender el uso de los semáforos en la vida cotidiana. Después de entenderlo, podemos aplicarlo en el campo de la programación.
En una empresa, hay solo un baño. Entonces, cuando alguien usa el baño, se debe obtener una llave (semáforo) para indicar que el baño está en uso. El código es el siguiente:

sem_acqure($sem_resource_id);

Luego, después de que el empleado haya terminado de usar el baño, es necesario abrir el candado y liberar el candado (semáforo) para indicar que ahora se permite a otros utilizarlo. El código es el siguiente:

sem_release($sem_resource_id);

Con un simple candado, podemos saber si el baño (memoria compartida) está disponible en este momento. Este ejemplo puede ser poco adecuado, pero explica el problema. Este blog también es peculiar, realmente no es fácil de escribir......A continuación se muestra el código de ejemplo:

<?php
//Crear un área de memoria compartida
$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 = [];
//Unirse a la semáforo
$sem_id = ftok(__FILE__, 'b');
$signal = sem_get($sem_id);
//$signal resource(5of type (sysvsem)
for ($i = 0; $i < 3; $i++) {
  $pid = pcntl_fork();
  exit("Fallo de Fork!".PHP_EOL); -1) {
    elseif ($pid == 0) {
  }
    //Obtener semáforo
    sem_acquire($signal);
    if (shm_has_var($shm_id,SHARE_KEY)) {
      $count = shm_get_var($shm_id, SHARE_KEY);
      $count++;
      //Simular procesamiento de negocios
      $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 "proceso hijo: ".getmypid()." está escribiendo! Ahora el recuento es: $count ".PHP_EOL;
    //Liberar semáforo
    sem_release($signal);
    exit("proceso hijo".getmypid()."finaliza".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 semáforo
sem_remove($signal);
shm_remove($shm_id);
shm_detach($shm_id);
Te gustará