semaphores - ¿Cómo evito que sem_open() falle con ENOSYS?
semaphore.h example (5)
Tengo dos sistemas Slackware Linux en los que el semáforo POSIX sem_open()
falla con errno establecido en 38. Código de ejemplo para reproducir a continuación (el código funciona bien en CentOS / RedHat).
¿Hay alguna opción de configuración del kernel o del sistema que pueda causar esto? ¿Otras sugerencias?
Los sistemas con problemas son Slackware 10.1.0 kernel 2.6.11 /lib/librt-2.3.4.so /lib/libpthread-0.10.so, pero el mismo código funciona en el núcleo mucho más antiguo de RedHat 9 2.4.20 / lib / librt -2.3.2.so /lib/tls/libpthread-0.29.so. (y también funciona en CentOS 5 kernel 2.6.18 /lib/librt-2.5.so /lib/i686/nosegneg/libpthread-2.5.so).
man sem_open
sugiere que errno significa que sem_open()
no es compatible con el sistema.
#define ENOSYS 38 /* Function not implemented */
El espacio de usuario sem_open()
está en librt
que librt
forma dinámica y librt
está presente en los sistemas afectados.
El sistema afectado afirma que admite semáforos POSIX: _POSIX_SEMAPHORES
es verdadero y sysconf(_SC_SEMAPHORES)
confirma.
Gracias, Kieran
Editar 1: He agregado más detalles sobre las versiones de software en uso y eliminé algunos comentarios irrelevantes.
Edición 2: / dev / shm está montado en los buenos sistemas y no está montado en los sistemas defectuosos. Montarlo no cambió el comportamiento en los sistemas afectados. Creo que / dev / shm también es necesario, pero sem_open () está fallando antes de eso, y strace lo admite.
# /* Quick''n''dirty test program to illustrate sem_open failure
#Run this file to auto-build test and run as a.out
# Build
gcc $0 -lrt
if [ $? -ne 0 ] ; then exit ; fi
# Run
$( dirname $0)/a.out
exit
*/
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <semaphore.h>
int main(int argc, char *argv[]) {
const char *SEM_NAME = "SHRMEM_SCXL"; /* name of mutex */
sem_t *mutex = SEM_FAILED; /* ptr to mutex */
#ifdef _POSIX_SEMAPHORES
printf("_POSIX_SEMAPHORES %ld/n", _POSIX_SEMAPHORES);
#else
puts("Undefined");
#endif
printf("sysconf %s/n", sysconf(_SC_SEMAPHORES) ? "Yes" : "No" );
mutex = sem_open(SEM_NAME, O_CREAT, 0666, 1);
if (mutex == SEM_FAILED) printf("Failed %d/n", errno);
else {
puts("Success - pause while you check /dev/shm ");
sleep(5);
sem_close(mutex);
sem_unlink(SEM_NAME);
}
}
¿Está / dev / shm montado? Es posible que las versiones anteriores de slackware no hayan montado este sistema de archivos al arrancar. Desde / etc / fstab:
tmpfs /dev/shm tmpfs defaults 0 0
Editar: Probablemente ese no sea el problema después de todo. Creo que puede que necesites actualizar tu kernel o incluso librt.
Edit2: Creo que para slackware 11, que creo que está utilizando, necesitará un núcleo más nuevo que 2.6.13 para usar las bibliotecas de subprocesamiento NPTL (libs en / lib / tls) que parecen ser necesarias para el sem_open para trabajo.
Edit3: Logré hacer que funcione con un cuadro de slackware 11 que tengo a) montando / dev / shm yb) estableciendo la variable de entorno LD_ASSUME_KERNEL
a 2.6.13 (cualquier versión del kernel> 2.6.12 funcionará). Eso parece funcionar a pesar de que el kernel es 2.6.11.11, pero otras cosas, como los hilos, podrían no funcionar.
Estaba trabajando con las colas de mensajes posix. Tengo el mismo error. Error de mq_open con errono 38 (ENOSYS).
El trabajo alrededor es reconstruir el kenel con POSIX MESSGE QUEUE habilitado en la configuración del kernel.
Esto construirá el kernel con soporte de cola de mensajes POSIX y funcionó para mí.
Gracias
La hipótesis del "proceso compartido no funciona" no tiene sentido para mí. No es que lo ayude, pero si tiene tiempo e inclinación, puede intentar lo siguiente para ver si el aspecto "proceso compartido" es lo que está fallando:
crea un semáforo usando sem_init en la memoria no compartida (para hilos). Si funciona, entonces los sema4s funcionan dentro del proceso.
repetir experimento en memoria compartida. Esto debería decirle si funcionan entre procesos. Tenga en cuenta que puede que necesite intentar usar el sema4 para ver si funciona entre procesos.
Las versiones anteriores de las bibliotecas de subprocesos no admiten compartir semáforos POSIX entre procesos. Del man sem_init
El argumento pshared indica si el semáforo es local al proceso actual (pshared es cero) o si se va a compartir entre varios procesos (pshared no es cero). LinuxThreads actualmente no admite semáforos compartidos por proceso, por lo que sem_init siempre devuelve con el error ENOSYS si pshared no es cero.
Como sem_open () crea semáforos con nombre, siempre intenta compartirlos entre procesos.
Para admitir el intercambio de semáforos anónimos entre los procesos con sem_init () en Slackware 10
- actualizar libpthread y (posiblemente) librt
- actualizar el kernel
Además, para admitir el uso compartido de semáforos con sem_open ()
agregue una línea a
/etc/fstab
para montar/dev/shm
como un tmpfstmpfs / dev / shm tmpfs valores predeterminados 0 0
ejecutar
mount /dev/shm
o reiniciar
Otra forma de compartir un semáforo entre procesos es utilizar semáforos SystemV.
Estos funcionan incluso cuando los semáforos POSIX compartidos no lo hacen (al menos en los sistemas descritos anteriormente).
Consulte http://www.linuxdevcenter.com/pub/a/linux/2007/05/24/semaphores-in-linux.html para ver ejemplos de los dos tipos de uso de semáforos.