Comment puis-je arrêter sem_open () échouer avec ENOSYS?
Question
J'ai deux systèmes Linux Slackware sur lesquels l'appel du sémaphore POSIX sem_open ()
échoue avec errno défini sur 38. Le code à reproduire ci-dessous (le code fonctionne correctement sous CentOS / RedHat).
Existe-t-il des options de configuration du noyau ou du système qui pourraient en être la cause? Autres suggestions?
Les systèmes en cause sont le noyau Slackware 10.1.0 2.6.11 /lib/librt-2.3.4.so /lib/libpthread-0.10.so, mais le même code fonctionne sur le noyau plus ancien RedHat 9 2.4.20 / lib / librt-2.3.2.so /lib/tls/libpthread-0.29.so. (et fonctionne également sur les noyaux CentOS 5 2.6.18 /lib/librt-2.5.so /lib/i686/nosegneg/libpthread-2.5.so).
man sem_open
suggère que cette erreur signifie que sem_open ()
n'est pas pris en charge par le système.
#define ENOSYS 38 /* Function not implemented */
L'espace utilisateur sem_open ()
se trouve dans librt
auquel nous lions de manière dynamique et librt
est présent sur les systèmes affectés.
Le système affecté prétend prendre en charge les sémaphores POSIX: _POSIX_SEMAPHORES
est true et sysconf (_SC_SEMAPHORES)
le confirme.
Merci, Kieran
Éditer 1: j'ai ajouté plus de détails sur les versions du logiciel en cours d'utilisation et j'ai supprimé certains commentaires inutiles.
Éditer 2: / dev / shm est monté sur les bons systèmes et non sur les mauvais. Le monter ne change pas le comportement sur les systèmes affectés. Je pense que / dev / shm est nécessaire aussi, mais sem_open () échoue avant cela, et strace le supporte.
# /* 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);
}
}
La solution
Est-ce que / dev / shm est monté? Les anciennes versions de slackware n'ont peut-être pas monté ce système de fichiers au démarrage. Depuis / etc / fstab:
tmpfs /dev/shm tmpfs defaults 0 0
Edit: Ce n’est probablement pas le problème après tout. Je pense que vous devrez peut-être simplement mettre à niveau votre noyau ou peut-être même votre bibliothèque.
Edit2: Je pense que pour slackware 11, que vous utilisez, vous aurez besoin d’un noyau plus récent que 2.6.13 pour utiliser les bibliothèques de threading NPTL (libs dans / lib / tls) qui semblent être nécessaires à le sem_open au travail.
Edit3: J'ai réussi à le faire fonctionner avec un slackware 11 que j'ai a) en montant) / dev / shm et b) en définissant la variable d'environnement LD_ASSUME_KERNEL
sur 2.6.13 (toute version du noyau > 2.6.12 fonctionnera). Cela semble fonctionner même si le noyau est 2.6.11.11, mais d'autres choses, comme les threads, pourraient ne pas l'être.
Autres conseils
Les anciennes versions des bibliothèques de threads ne prennent pas en charge le partage de sémaphores POSIX entre processus. De man sem_init
L'argument pshared indique si le sémaphore est local au processus en cours (pshared est zéro) ou doit être partagé entre plusieurs processus (pshared n’est pas nul). LinuxThreads n'est actuellement pas supporte les sémaphores partagés par le processus, ainsi sem_init revient toujours avec erreur ENOSYS si pshared n’est pas nul.
Comme sem_open () crée des sémaphores nommés, il essaie toujours de les partager entre processus.
Pour prendre en charge le partage de sémaphores anonymes entre processus avec sem_init () sur Slackware 10
- met à jour libpthread et (éventuellement) librt
- mettre à jour le noyau
De plus, pour prendre en charge le partage de sémaphores nommés avec sem_open ()
-
ajoutez une ligne à
/ etc / fstab
pour monter/ dev / shm
en tant que tmpfstmpfs / dev / shm tmpfs par défaut 0 0
-
exécuter
mount / dev / shm
ou redémarrer
Le "processus de traitement des sema4 partagés ne fonctionne pas" l'hypothèse a du sens pour moi. Ce n’est pas que cela vous aide, mais si vous avez le temps et l’envie, essayez d’essayer ce qui suit pour voir si le " processus-partagé " aspect est ce qui échoue:
-
créez un sémaphore en utilisant sem_init dans la mémoire non partagée (pour les threads). Si cela fonctionne, sema4s fonctionne dans le processus.
-
répéter l'expérience dans la mémoire partagée. Cela devrait vous dire s'ils fonctionnent entre les processus. Notez que vous devrez peut-être réellement utiliser la sema4 pour voir si elle fonctionne entre les processus.
Un autre moyen de partager un sémaphore entre plusieurs processus consiste à utiliser des sémaphores SystemV.
Ils fonctionnent même là où les sémaphores POSIX partagés ne fonctionnent pas (du moins sur les systèmes décrits ci-dessus).
Voir http: // www.linuxdevcenter.com/pub/a/linux/2007/05/24/semaphores-in-linux.html pour des exemples d'utilisation des deux types de sémaphores.
Je travaillais avec des files de messages posix. La même erreur mq_open a échoué avec erreur 38 (ENOSYS).
Le travail consiste à reconstruire le kenel avec POSIX MESSGE QUEUE activé dans la configuration du noyau.
Ceci construira le noyau avec le support de la file d’attente de messages POSIX et cela a fonctionné pour moi.
Merci