C 我如何阻止sem_open()在ENOSYS上失败?
我有两个Slackware Linux系统,在这两个系统上,POSIX信号量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
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)
可以在受影响的系统上创建非共享信号量。我没有测试非共享信号量是否可以跨进程可靠地共享。手册页上说它们不适合分享,所以我不想依赖它们。