C 我如何阻止sem_open()在ENOSYS上失败?

C 我如何阻止sem_open()在ENOSYS上失败?,c,linux,ipc,posix,semaphore,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/l

我有两个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/nosegne/libpthread-2.5.so)

man sem_open
建议此错误不表示系统不支持
sem_open()

#define ENOSYS          38      /* Function not implemented */
sem\u open()

受影响的系统声称支持POSIX信号量:
\u POSIX\u信号量
为真,并且
sysconf(\u SC\u信号量)
确认了这一点

谢谢, 基兰

编辑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);
 }
}
#/*说明sem#U打开故障的快速脏测试程序
#运行此文件以自动生成测试并作为.out运行
#建造
gcc$0-轻轨
如果[$?-ne 0];然后退出;fi
#跑
$(dirname$0)/a.out
出口
*/
#包括
#包括
#包括
#包括
#包括
int main(int argc,char*argv[]){
const char*SEM_NAME=“SHRMEM_SCXL”/*互斥体的名称*/
sem_t*mutex=sem_失败;/*ptr到mutex*/
#ifdef_POSIX_信号量
printf(“\u POSIX\u信号量%ld\n”,\u POSIX\u信号量);
#否则
看跌期权(“未定义”);
#恩迪夫
printf(“sysconf%s\n”,sysconf(_SC_信号量)?“是”:“否”);
互斥量=sem_open(sem_NAME,O_CREAT,0666,1);
if(mutex==SEM_FAILED)printf(“FAILED%d\n”,errno);
否则{
放置(“成功-检查/dev/shm时暂停”);
睡眠(5);
sem_close(互斥);
sem_取消链接(sem_名称);
}
}

是否安装了/dev/shm?旧版本的slackware可能在启动时没有安装此文件系统。从/etc/fstab:

tmpfs  /dev/shm  tmpfs  defaults  0   0
编辑:这可能根本不是问题所在。我想你可能只需要升级你的内核或者甚至是librt

Edit2:我认为对于slackware 11,我认为您正在使用,您需要一个比2.6.13更新的内核来使用NPTL线程库(libs in/lib/tls),这似乎是打开sem_工作所必需的


Edit3:我通过a)挂载/dev/shm和b)将环境变量
LD\u假设内核
设置为2.6.13(任何>2.6.12的内核版本都可以使用),设法让它与我拥有的slackware 11设备一起工作。即使内核是2.6.11.11,这似乎也行得通,但线程之类的其他东西可能不行。

旧版本的线程库不支持在进程之间共享POSIX信号量。从
man sem\u init

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

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

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

  • 升级libpthread和(可能)librt
  • 升级内核
此外,为了支持与sem_open()共享命名信号量

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

    tmpfs/dev/shm tmpfs默认值为0

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

    • 我觉得“进程共享的语义4不起作用”的假设有些道理。这并不是说它对您有帮助,但如果您有时间和意愿,您可能希望尝试以下方法,看看“流程共享”方面是否是失败的方面:

    • 在非共享内存(对于线程)中使用sem_init创建信号量。如果有效,则在流程中有效

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


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

      即使在共享POSIX信号量不起作用的情况下(至少在上面描述的系统上),它们也能起作用


      有关这两种信号量使用的示例,请参阅。

      我在使用posix消息队列时,遇到了相同的错误mq_open在使用errono 38(ENOSYS)时失败

      周围的工作是在内核配置中启用POSIX消息队列的情况下重建kenel

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


      谢谢

      谢谢您的帮助-这可能会在Slackware 11上修复它,但事实证明我们使用的是Slackware 10。在实时系统上升级库/内核的风险太大,所以我正在研究一种代码解决方法。谢谢。在我写我的“答案”之前,我验证了
      sem_init(pshared=0)
      可以在受影响的系统上创建非共享信号量。我没有测试非共享信号量是否可以跨进程可靠地共享。手册页上说它们不适合分享,所以我不想依赖它们。