谁初始化信号量?

3
所以,问题是:我正在为我的大学项目编写一个“聊天模拟器”。 不深入细节,客户端可以多次运行,所有实例都使用由信号量(以及其他内容)保护的相同的共享内存段。
客户端在未知的时间进入和退出系统。当第一个客户端进入系统时,它应该创建一个信号量,使用共享内存并释放。但是,如果有任何其他客户端进入系统,则必须在获取共享内存访问之前等待信号量。
现在,我觉得我忽略了一些明显的东西——如何初始化信号量? 如果我使用semget(42, 1, IPC_CREAT),那么结果信号量很可能是0——但我不能将其提高以初始化,因为0可能意味着已经有进程在临界区中。换句话说,我不知道我是否刚刚创建了默认值为0的信号量,或者是否有一个进程正在等待信号量。
伪代码如下:
if(semaphore_not_exists(42))
{
    create_sem;
    raise_sem;
}
else
{
    get_sem_handle;
}
wait_on_sem;
critical_section;
release_sem;

那么,我该如何确保信号量还没有被其他进程创建,以便安全地初始化它?如果我使用IPC_EXCL,请求将失败,但我不知道接下来应该怎么做。

1
我认为所有信号量的用户都需要获得已经初始化的信号量。否则,信号量本身的初始化就会受到竞争条件的影响。 - UmNyobe
你是否因为某些原因需要使用SysV信号量? - zwol
这是我在课程中学到的,但我想采用另一种方法应该也没有问题。为什么?它们已经过时了吗? - Maciej Stachowski
POSIX信号量和共享内存是更现代化、设计较好的API。然而,我不确定它们是否存在相同的问题。 - zwol
2个回答

3
您可以按以下步骤操作:
  1. 调用semget(key, nsems, IPC_CREAT | IPC_EXCL)。如果成功,您现在已经创建了一个新的信号量集,然后应通过semctl()设置它。
  2. 如果前面的semget()失败了,则再次调用semget(),但不带IPC_EXCL标志。
我还建议使用锁文件(通过flock()或类似方式),以确保在初始化之前不使用信号量集。

0
我认为所有使用信号量的用户都需要获得已经初始化的信号量。否则,信号量本身的初始化将受到竞争条件的影响。 您可以在系统引导时拥有一个守护进程来初始化信号量并进行维护。
create_sem;
raise_sem;

当客户端只是执行时

get_sem_handle;

那么,唯一的选择就是拥有一个完全独立的进程来初始化信号量?而且我每次在启动客户端之前都必须运行它(因为我不能真正地在大学计算机上调整init脚本)?嗯,希望有更优雅的解决方案... - Maciej Stachowski

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