Come posso interrompere il fallimento di sem_open () con ENOSYS?
Domanda
Ho due sistemi Slackware Linux su cui la chiamata del semaforo POSIX sem_open ()
non riesce con errno impostato su 38. Codice di esempio da riprodurre di seguito (il codice funziona bene su CentOS / RedHat).
Esistono opzioni di configurazione del kernel o del sistema che potrebbero causare questo? Altri suggerimenti?
I sistemi con problemi sono il kernel Slackware 10.1.0 2.6.11 /lib/librt-2.3.4.so /lib/libpthread-0.10.so, ma lo stesso codice funziona sul kernel RedHat 9 molto vecchio 2.4.20 / lib / librt-2.3.2.so /lib/tls/libpthread-0.29.so. (e funziona anche con il kernel 2.6.18 di CentOS 5 /lib/librt-2.5.so /lib/i686/nosegneg/libpthread-2.5.so).
man sem_open
suggerisce che questo errore significa che sem_open ()
non è supportato dal sistema.
#define ENOSYS 38 /* Function not implemented */
Lo spazio utente sem_open ()
è in librt
che colleghiamo dinamicamente e librt
è presente sui sistemi interessati.
Il sistema interessato afferma di supportare i semafori POSIX: _POSIX_SEMAPHORES
è vero e sysconf (_SC_SEMAPHORES)
lo conferma.
Grazie, Kieran
Modifica 1: ho aggiunto maggiori dettagli sulle versioni del software in uso e rimosso alcuni commenti irrilevanti.
Modifica 2: / dev / shm è montato sui sistemi buoni e non sui sistemi cattivi. Il montaggio non ha modificato il comportamento sui sistemi interessati. Penso che anche / dev / shm sia necessario ma sem_open () non riesce prima, e strace lo supporta.
# /* Quick'n'dirty test program to illustrate sem_open failure
#Run this file to auto-build test and run as a.out
# Build
gcc <*> -lrt
if [ $? -ne 0 ] ; then exit ; fi
# Run
$( dirname <*>)/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);
}
}
Soluzione
/ dev / shm è montato? Versioni precedenti di slackware potrebbero non aver montato questo filesystem all'avvio. Da / etc / fstab:
tmpfs /dev/shm tmpfs defaults 0 0
Modifica: probabilmente non è questo il problema. Penso che potresti aver solo bisogno di aggiornare il tuo kernel o magari anche di librt.
Edit2: Penso che per lo slackware 11, che penso tu stia usando, avrai bisogno di un kernel più recente della 2.6.13 per usare le librerie di threading NPTL (libs in / lib / tls) che sembrano essere richieste per sem_open per funzionare.
Edit3: sono riuscito a farlo funzionare con una slackware 11 box che ho a) montaggio / dev / shm eb) impostando la variabile di ambiente LD_ASSUME_KERNEL
su 2.6.13 (qualsiasi versione del kernel > 2.6.12 funzionerà). Sembra funzionare anche se il kernel è 2.6.11.11, ma altre cose come i thread potrebbero non funzionare.
Altri suggerimenti
Le versioni precedenti delle librerie di threading non supportano la condivisione di semafori POSIX tra processi. Da man sem_init
L'argomento pshared indica se il semaforo è locale per il processo corrente (pshared è zero) o deve essere condiviso tra più processi (pshared non è zero). LinuxThreads attualmente no supporta i semafori condivisi dal processo, quindi sem_init restituisce sempre con errore ENOSYS se pshared non è zero.
Mentre sem_open () crea semafori nominati, cerca sempre di condividerli tra processi.
Supportare la condivisione di semafori anonimi tra processi con sem_init () su Slackware 10
- aggiorna libpthread e (possibilmente) librt
- aggiorna il kernel
Inoltre, per supportare la condivisione di semafori denominati con sem_open ()
-
aggiungi una linea a
/ etc / fstab
per montare/ dev / shm
come tmpfstmpfs / dev / shm tmpfs predefinito 0 0
-
esegui
mount / dev / shm
o riavvia
Il processo "sema4s condiviso non funziona" l'ipotesi ha un senso per me. Non che ti aiuti, ma se hai tempo e inclinazione potresti voler provare quanto segue, per vedere se il "processo condiviso" " l'aspetto è ciò che sta fallendo:
-
crea un semaforo usando sem_init nella memoria non condivisa (per i thread). Se funziona, allora i sema4 funzionano all'interno del processo.
-
ripeti l'esperimento nella memoria condivisa. Questo dovrebbe dirti se funzionano tra i processi. Si noti che potrebbe essere necessario provare effettivamente a USARE sema4 per vedere se funziona tra i processi.
Un altro modo per condividere un semaforo tra processi è usare i semafori SystemV.
Funzionano anche dove i semafori POSIX condivisi non lo fanno (almeno sui sistemi sopra descritti).
Vedi http: // www.linuxdevcenter.com/pub/a/linux/2007/05/24/semaphores-in-linux.html per esempi dei due tipi di utilizzo dei semafori.
Stavo lavorando con le code dei messaggi posix ho avuto lo stesso errore mq_open non è riuscito con errono 38 (ENOSYS).
Lo scopo principale è ricostruire il kenel con POSIX MESSGE QUEUE abilitato nella configurazione del kernel.
Questo genererà il kernel con il supporto per la coda dei messaggi POSIX e ha funzionato per me.
Grazie