Si hay un punto en la ejecución de su programa cuando se sabe que todos los procesos que necesitan abrir el segmento de memoria compartida ya lo han hecho, puede desvincularlo con seguridad. La desvinculación elimina el objeto del espacio de nombres global, pero aún permanece mientras haya al menos un proceso que mantenga abierto su descriptor de archivo. Si se produce un bloqueo después de ese punto, el descriptor de archivo se cierra automáticamente y el recuento de referencias se reduce. Una vez que no quedan descriptores abiertos en el bloque de memoria compartida desvinculado, se elimina.
Esto es útil en el siguiente escenario:un proceso crea un bloque de memoria compartida, lo desvincula y luego se bifurca. El hijo hereda el descriptor de archivo y puede usar el bloque de memoria compartida para comunicarse con el padre. Una vez que ambos procesos terminan, el bloque se elimina automáticamente cuando se cierran ambos descriptores de archivo.
Mientras está desvinculado, el bloque de memoria compartida no está disponible para que otros procesos lo abran. Mientras tanto, si uno usa shm_open()
con el mismo nombre que el bloque desvinculado, en su lugar se crearía un bloque de memoria compartida nuevo y completamente diferente.
Encontré una manera de usar un comando del sistema y el comando "fuser" de Linux que permite enumerar los procesos que abrieron un archivo. De esta manera, puede verificar si el archivo de memoria compartida (ubicado en /dev/shm") todavía está en uso y eliminarlo si no. Tenga en cuenta que las operaciones de verificación / eliminación / creación deben incluirse en una sección crítica entre procesos utilizando un mutex con nombre o un semáforo con nombre o un bloqueo de archivo.
std::string shm_file = "/dev/shm/" + service_name + "Shm";
std::string cmd_line = "if [ -f " + shm_file + " ] ; then if ! fuser -s " + shm_file + " ; then rm -f " + shm_file + " ; else exit 2 ; fi else exit 3 ; fi";
int res = system(cmd_line.c_str());
switch (WEXITSTATUS(res)) {
case 0: _logger.warning ("The shared memory file " + shm_file + " was found orphan and is deleted"); break;
case 1: _logger.critical("The shared memory file " + shm_file + " was found orphan and cannot be deleted"); break;
case 2: _logger.trace ("The shared memory file " + shm_file + " is linked to alive processes"); break;
case 3: _logger.trace ("The shared memory file " + shm_file + " is not found"); break;
}
No, al menos en Linux, el kernel no contiene nada que pueda hacer esto. Depende de alguna aplicación llamar a shm_unlink() en algún momento para deshacerse de un segmento de memoria compartida.