如何阻止sem_open()与ENOSYS失败?

我有两个Slackware Linux系统,POSIX semaphore sem_open()调用失败,errno设置为38.下面重现的示例代码(代码在CentOS / RedHat上正常工作)。

有没有可能会导致此问题的内核或系统configuration选项? 其他build议?

有问题的系统是Slackware 10.1.0内核2.6.11 /lib/librt-2.3.4.so /lib/libpthread-0.10.so,但是相同的代码在更老的RedHat 9内核上工作2.4.20 / lib / librt -2.3.2.so /lib/tls/libpthread-0.29.so。 (也适用于CentOS 5内核2.6.18 /lib/librt-2.5.so /lib/i686/nosegneg/libpthread-2.5.so)。

man sem_open表明这个errno意味着sem_open()不被系统支持。

 #define ENOSYS 38 /* Function not implemented */ 

sem_open()用户空间在librt ,我们dynamic链接, librt在受影响的系统上。

受影响的系统声称支持POSIX信号量_POSIX_SEMAPHORES为true, sysconf(_SC_SEMAPHORES)确认这一点。

谢谢,基兰

编辑1:我已经在使用的软件版本添加更多的细节,并删除了一些不相关的评论。

编辑2:/ dev / shm安装在好的系统上,而不是安装在坏的系统上。 挂载它并没有改变受影响系统的行为。 我认为/ dev / shm也是必要的,但是sem_open()在这之前是失败的,strace支持这个。

 # /* 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); } } 

是/ dev / shm挂载? 老版本的slackware在启动时可能没有挂载这个文件系统。 从/ etc / fstab:

 tmpfs /dev/shm tmpfs defaults 0 0 

编辑:这可能不是问题毕竟。 我想你可能只需要升级你的内核,甚至可能是librt。

编辑2:我认为对于我认为你正在使用的slackware 11,你将需要一个比2.6.13更新的内核来使用似乎是sem_open所需的NPTL线程库(/ lib / tls中的库)工作。

编辑3:我设法得到它与一个slackware 11盒我有安装/ dev / shm和b)设置环境变量LD_ASSUME_KERNEL 2.6.13(任何内核版本> 2.6.12将工作)。 这似乎工作,即使内核是2.6.11.11,但其他像线程可能不会。

老版本的线程库不支持在进程之间共享POSIX信号量。 从man sem_init

pshared参数指示信号量是当前进程的本地(pshared为零)还是要在多个进程之间共享(pshared不为零)。 LinuxThreads目前不支持进程共享信号量,因此,如果pshared不为零,则sem_init始终返回错误ENOSYS。

当sem_open()创建命名的信号量时,它总是试图在进程之间共享它们。

支持在Slackware 10上使用sem_init()在进程之间共享匿名信号量

  • 升级libpthread和(可能)librt
  • 升级内核

另外,为了支持与sem_open()共享命名的信号量

  • /etc/fstab添加一行以将/dev/shm挂载为tmpfs

    tmpfs / dev / shm tmpfs默认值0 0

  • 运行mount /dev/shm或重新启动

“过程共享sema4s不起作用”的假设对我来说是有道理的。 不是说它对你有帮助,但是如果你有时间和倾向,你可能想要尝试下面的内容,看看“过程共享”方面是否是失败的:

  1. 在非共享内存(对于线程)中使用sem_init创建一个信号量。 如果有效,那么在这个过程中sema4s会工作。

  2. 在共享内存中重复实验。 这应该告诉你他们是否在进程之间工作。 请注意,您可能需要真正尝试使用sema4来查看它是否在进程之间工作。

另一种跨进程共享信号量的方法是使用SystemV信号量。

即使在共享的POSIX信号量没有的情况下(至少在上面描述的系统中),这些工作也是可行的。

请参阅http://www.linuxdevcenter.com/pub/a/linux/2007/05/24/semaphores-in-linux.html两种信号量使用的示例&#x3002;

我正在posix消息队列我有同样的错误mq_open errono 38(ENOSYS)失败。

工作的一个重点是在内核配置中使用POSIX MESSGE QUEUE来重建kenel。

这将建立与POSIX消息队列支持的内核,它为我工作。

谢谢