如何使用ENOSYS阻止sem_open()失败?

时间:2008-11-06 20:25:18

标签: c linux ipc posix semaphore

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

是否有可能导致此问题的内核或系统配置选项?其他建议?

有问题的系统是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表示此错误意味着系统不支持sem_open()

#define ENOSYS          38      /* Function not implemented */

sem_open()用户空间位于librt我们动态关联,librt出现在受影响的系统上。

受影响的系统声称支持POSIX信号量:_POSIX_SEMAPHORES为真,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);
 }
}

5 个答案:

答案 0 :(得分:5)

是/ dev / shm安装?较旧版本的slackware可能没有在启动时挂载此文件系统。来自/ etc / fstab:

tmpfs  /dev/shm  tmpfs  defaults  0   0

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

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

Edit3:我设法让它与slackware 11盒子一起使用a)mount / dev / shm和b)将环境变量LD_ASSUME_KERNEL设置为2.6.13(任何内核版本&gt; 2.6) .12会奏效)。即使内核是2.6.11.11,这似乎也可行,但其他类似线程的东西可能不会。

答案 1 :(得分:1)

较旧版本的线程库不支持在进程之间共享POSIX信号量。来自man sem_init

  

pshared参数指示信号量是否是本地信号量   当前进程(pshared为零)或将在几个之间共享   进程(pshared不为零)。 LinuxThreads目前没有   支持进程共享信号量,因此sem_init总是返回   如果pshared不为零,则出现错误ENOSYS。

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

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

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

此外,支持使用sem_open()

共享命名信号量
  • /etc/fstab添加一行以挂载/dev/shm作为tmpfs

    tmpfs / dev / shm tmpfs defaults 0 0

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

答案 2 :(得分:1)

“进程共享sema4s不起作用”假设对我有意义。并不是它对你有帮助,但如果你有时间和倾向,你可能想尝试以下方法,看看“进程共享”方面是否失败:

  1. 在非共享内存中使用sem_init创建信号量(对于线程)。如果它有效,则sema4s在该过程中工作。

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

答案 3 :(得分:0)

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

即使共享POSIX信号量没有(至少在上述系统上),它们也能工作。

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

答案 4 :(得分:0)

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

工作重点是在内核配置中启用POSIX MESSGE QUEUE来重建kenel。

这将构建具有POSIX消息队列支持的内核,它对我有用。

由于