为什么 sem_init()、sem_getvalue()、sem_destroy() 在 Mac OS X 上被弃用——什么替代了它们?

Why are sem_init(), sem_getvalue(), sem_destroy() deprecated on Mac OS X — and what replaces them?

当我使用 POSIX sem_init() 函数编译程序时,我收到一个编译警告(错误,因为我通常使用 -Werror)当我使用 GCC 4.9.1 或来自 XCode 6.1.1 的 Clang (Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn)) 版本在 Mac OS X 10.10.1 (Yosemite) 上编译。快速查看 /usr/include/sys/semaphore.h 表明该函数在其声明后确实有一个 __deprecated 标记,就像 sem_getvalue()sem_destroy().

问题:

  1. 既然在 POSIX 规范中没有任何弃用的提示,为什么在 Mac OS X 上将这三个函数挑出来弃用?

  2. 鉴于它们已被弃用,替代品是什么,为什么首选替代品?

(我确实检查了 Ask Different first; there are no questions tagged 并且没有询问有关已弃用系统调用的问题 — 只有程序。)

我 运行 在尝试将我正在研究的库移植到 OS X 时自己遇到了这个问题。我搜索了一段时间但没有找到很好的答案。当我确实找到答案时,我有点不安:答案实际上是 "if Apple implemented POSIX unnamed semaphores, how many X Serves would you buy?".

总结它们被弃用的原因以及某些功能仍未实现的原因:

  • 单一 UNIX 规范的附录 9 声明它们不是强制接口
  • "Most portable code" 使用 SYSV 信号量
  • 向后兼容 POSIX 命名信号量,共享 sem_t 类型是困难的

至于该怎么做,我选择了 GCD 信号量。至于为什么首选替代品:它是 vanilla OS X 上唯一可用的本机未命名信号量接口。显然 GCD 帮助他们销售了更多的 X 服务。恐怕没有更好的答案了。

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

#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
}

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