3

我有两个 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_opensem_open()表明系统不支持此 errno 方法。

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

5 回答 5

5

/dev/shm 是否已安装?旧版本的 slackware 可能没有在引导时挂载这个文件系统。从 /etc/fstab:

tmpfs  /dev/shm  tmpfs  defaults  0   0

编辑:毕竟这可能不是问题。我认为您可能只需要升级内核甚至 librt。

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

Edit3:我设法让它与我拥有的 slackware 11 盒子一起工作,方法是 a)安装 /dev/shm 和 b)将环境变量设置LD_ASSUME_KERNEL为 2.6.13(任何内核版本> 2.6.12 都可以使用)。即使内核是 2.6.11.11,这似乎也有效,但线程等其他东西可能不会。

于 2008-11-06T21:33:38.440 回答
1

旧版本的线程库不支持在进程之间共享 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或重启

于 2008-11-07T12:20:19.667 回答
1

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

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

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

于 2008-11-07T16:15:05.717 回答
0

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

即使在共享 POSIX 信号量不起作用的情况下(至少在上述系统上),这些也确实有效。

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

于 2008-11-07T16:38:49.427 回答
0

我正在使用POSIX消息队列,我遇到了同样的错误,mq_open 失败并出现错误 38 (ENOSYS)。

解决方法是在内核配置中启用 POSIX MESSAGE QUEUE 来重建内核。

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

于 2010-05-19T07:02:44.897 回答