为什么在Mac OS X上sem_init()、sem_getvalue()和sem_destroy()被弃用了,有什么替代品?

50
当我使用 POSIX 的sem_init()函数编译程序时,在Mac OS X 10.10.1 (Yosemite)上使用GCC 4.9.1或来自XCode 6.1.1的Clang版本(Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn))编译时,会得到一个编译警告(因为我通常使用-Werror),提示该函数已经被弃用。快速查看/usr/include/sys/semaphore.h可以发现,函数确实在声明后有一个__deprecated标记,sem_getvalue()sem_destroy()同样如此。

问题:

  1. 考虑到 POSIX 规范中没有任何关于废弃的提示,为什么这三个函数在 Mac OS X 上被单独标记为废弃?

  2. 既然它们已经被废弃,那么它们的替代方案是什么,为什么这个替代方案更受欢迎?

我先检查了 Ask Different;没有标记为 的问题,也没有询问废弃的系统调用的问题 - 只有程序。


1
与https://dev59.com/23M_5IYBdhLWcg3wWRuV和https://dev59.com/1HLYa4cB1Zd3GeqPWVSY#16655541相关。 - Iskar Jarak
1
@IskarJarak:这两个问题中的第一个似乎在实践中解决了我的问题,尽管仍然存在“为什么”(比如,“为什么Mac OS X不支持未命名信号量?”)这个问题没有解决。但这可能是最难回答的部分。由于我的代码无法编译,因此我无法从sem_init()函数得到ENOSYS错误的提示。 - Jonathan Leffler
另一个也许更加正式的答案来源可以在“Mac开发”的“Core OS”子版块中通过https://devforums.apple.com找到。 - Alex Reynolds
2
@JonathanLeffler,在进程间实现控制结构在开发和执行方面都是相当大的开销。在线程世界中,这种接口并没有太多用处,他们可能只是不想为此付出代价。他们处理这个问题的方式实际上非常令人恼火,只提供一个返回错误的接口。这再次表明,他们对POSIX的遵循只是表面的,他们并没有真正致力于提供一个开放的环境。 - Jens Gustedt
这个回答解决了你的问题吗?在OS X上使用sem_init - G Huxley
1个回答

51

在尝试将我正在开发的一个库移植到OS X时,我自己遇到了这个问题。我搜索了一段时间,没有找到一个很好的答案。当我找到答案时,我有点不安:答案实际上是“如果Apple实现了POSIX未命名信号量,你会购买多少台X Serve?”

总结一下为什么它们被弃用以及一些功能为何保持未实现的原因:

  • Single UNIX规范的附录9指出它们不是强制性接口
  • “大多数可移植代码”使用SYSV信号量
  • 与POSIX命名信号量的向后兼容性,其共享sem_t类型,很难实现

至于代替方法,我选择了GCD信号量。关于为什么首选此替代方式:它是Vanilla OS X上唯一可用的本地未命名信号量接口。显然,GCD帮助他们销售更多的X Serve。我担心没有更好的答案了。

但是,希望下面的代码对您有所帮助。所有这些的结果是,您实际上必须实现自己的可移植信号量接口:

#ifdef __APPLE__
#include <dispatch/dispatch.h>
#else
#include <semaphore.h>
#endif

struct rk_sema {
#ifdef __APPLE__
    dispatch_semaphore_t    sem;
#else
    sem_t                   sem;
#endif
};


static inline void
rk_sema_init(struct rk_sema *s, uint32_t value)
{
#ifdef __APPLE__
    dispatch_semaphore_t *sem = &s->sem;

    *sem = dispatch_semaphore_create(value);
#else
    sem_init(&s->sem, 0, value);
#endif
}

static inline void
rk_sema_wait(struct rk_sema *s)
{

#ifdef __APPLE__
    dispatch_semaphore_wait(s->sem, DISPATCH_TIME_FOREVER);
#else
    int r;

    do {
            r = sem_wait(&s->sem);
    } while (r == -1 && errno == EINTR);
#endif
}

static inline void
rk_sema_post(struct rk_sema *s)
{

#ifdef __APPLE__
    dispatch_semaphore_signal(s->sem);
#else
    sem_post(&s->sem);
#endif
}

这是我关心的最小功能集合;你的需求可能会有所不同。希望这对你有所帮助。


4
我想我想把“销毁函数”添加到集合中,但这是个有用的起点。谢谢。 - Jonathan Leffler
非常好,你提供了我需要的东西。如果苹果没有实现无名信号量,那真的应该是一个错误。不管怎样,在我按照你提供的方式更改代码后,现在它可以正常运行了。 - Yongwei Wu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接