POSIX 中是否允许复制未命名信号量?

JS_*_*JS_ 3 c linux posix semaphore glibc

POSIX 有未命名(基于内存)信号量的概念。它们在某个内存位置用 初始化sem_init,然后我们可以用 和 来使用sem_post它们sem_wait。我想知道是否可以将“信号量句柄”复制到其他内存位置,然后将其用作正常的、独立的、初始化良好的信号量。

换句话说,这样做是否合法:

#include "semaphore.h"

int main()
{
  sem_t s1;
  sem_init(&s1, 0, 1); /* Initialize unnamed semaphore */

  sem_t s2 = s1; /* Copy to some other memory location */
  sem_wait(&s2); /* Lock on the semaphore */
  sem_post(&s2); /* Release the lock */ 
  
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

这似乎在 Linux 上工作得很好,没有任何问题。在 glibc 中,信号量似乎只是 2 或 3 个整数,使用原子指令来确保它是线程(甚至进程)安全的: https: //github.com/bminor/glibc/blob/ 6c2f050dbe11fb4ed0a401a5f25731f2aa53046b/htl/pt-internal.h#L333所以,如果我复制信号量,它只会复制它的当前状态(它的值),这很好。

然而,我想知道这是否只是偶然,我们不能依赖其他 POSIX 实现的这种行为。

例如,我发现在 FreeRTOS+POSIX 层(https://freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_POSIX/index.html)中,这是无效的,因为它的信号量是在 FreeRTOS 信号量之上实现的,并且FreeRTOS 内核跟踪初始化信号量的地址。因此,不可能只是盲目地将信号量句柄复制到不同的内存位置并然后使用它。当然,请注意,FreeRTOS+POSIX 库并不声称兼容 POSIX,它仅实现了 POSIX API 的一小部分,因此这只是一个示例。

我在 POSIX 官方文档中找不到任何提及此行为的信息。

Rac*_* K. 5

POSIX规范提到:

对于屏障、条件变量、互斥锁和读写锁,如果进程共享属性设置为PTHREAD_PROCESS_PRIVATE,则只有用于初始化它的地址处的同步对象才能用于执行同步。锁定、解锁或销毁对象时引用同一对象的另一个映射的效果是未定义的。如果进程共享属性设置为PTHREAD_PROCESS_SHARED,则只能使用同步对象本身进行同步;但是,不需要在用于初始化它的地址处引用它(即可以使用同一对象的另一个映射)。锁定、解锁或销毁对象时引用对象副本的效果是未定义的

因此,为了符合 POSIX 标准,不允许复制。