问题:如何使用SysV信号量在两个进程之间进行同步(让我们称之为procA
和procB
),假设它们都是从shell独立运行的(它们都不是由shell生成的) fork
/ exec
组合)并且信号量必须由这两个过程之一创建。
引用man semget
:
新创建的集合中的信号量值 不定。 (POSIX.1-2001在这一点上是明确的。)虽然 与许多其他实现一样,Linux初始化信号量 值为0,便携式应用程序不能依赖于此:它 应该明确地将信号量初始化为所需的值。
假设我们想编写仅依赖于POSIX保证的可移植代码,但没有特定于Linux的保证。非常好,因此不可能以原子方式创建信号量集并初始化它。这必须通过两个单独的调用来完成。
因此,为procA
创建信号量的代码看起来像这样:
int sem_id = semget(key, nsems, IPC_CREAT | S_IRWXU);
同样对于procB
- 这样,无论哪个进程第一次都需要信号量,它也会创建它们;否则,它只是获取信号量集的ID并准备好使用它。
需要初始化时会出现问题。初始化指令当然是semctl
SETALL
- 但是:•初始化应该只进行一次,并且•初始化应该在使用信号量之前完成。这当然可以由...信号量强制执行,但遗憾的是这样的解决方案是递归的:我们需要信号量来设置信号量,信号量本身需要设置信号量等等。
是否可以仅使用sysV信号量进行此操作,或者我是否正确地假设我必须求助于其他IPC设施(如信号或消息队列)才能可靠地设置这些信号量?
答案 0 :(得分:0)
根据我的经验,这不是现实世界中的问题。我将IPC创建和初始化放在一个单独的程序中,该程序在运行任何客户端程序之前由系统启动脚本调用。 IPC资源永远不会被删除,只有在重新启动时才会消失。
如果我必须动态创建资源,我会让创建者程序作为单独的用户启动,并使用仅拥有者权限创建资源。然后它会初始化它,最后向客户端的用户授予权限,然后退出。
客户只需在ENOENT或EACCES上重试,也许只需要使用nanosleep。
第二,虽然我可能只使用POSIX信号量,因为sem_open(3)让你指定O_EXCL和一个初始值。老Sys V的习惯很难打破。