【问题标题】:how use three semaphore for server clients architecture with shared memory如何将三个信号量用于具有共享内存的服务器客户端架构
【发布时间】:2017-12-29 13:13:12
【问题描述】:

我正在实现一个带有客户端程序的服务器。通信使用共享内存。为了控制对公共资源的访问,我使用了信号量。如果客户端是服务器的新手,服务器会为客户端生成一个 id。客户端保存它的 id 并将在进一步的请求中发送这个 id。 我正在使用以下代码在服务器和客户端之间进行通信。此解决方案仅适用于一台服务器和一台客户端。

服务器:

#include <semaphore.h>

sem_t* server = sem_open(SEM_1, O_CREAT | O_EXCL, 0600, 1);
sem_t* client = sem_open(SEM_2, O_CREAT | O_EXCL, 0600, 0);
//other stuff
while (!want_quit)
{
  sem_wait(client)
  //get id of client from shared memory or generate id for client
  //get the command from the client via shared memory
  //process command
  //write result back to shared memory
  sem_post(server)
}

客户:

#include <semaphore.h>

sem_t* s1 = sem_open(SEM_1, 0);
sem_t* s2 = sem_open(SEM_2, 0);
do
{
   //wait for the server
   sem_wait(s1);
   //get result from last command from shared memory
   //send new request to server by writing command into shared memory
   sem_post(s2);
} while (command from shm != CLOSE);

服务器应该工作/管理一个以上的客户端。我以为我可以通过第三个信号量来解决这个问题,但是我遇到了死锁问题,或者客户端处理了另一个客户端的结果。

我使用第三个信号量的解决方案如下所示:

服务器:

sem_wait(clients); sem_wait(client); sem_post(server);

客户:

sem_wait(s1); sem_post(clients); sem_post(server);

我该如何解决这个挑战?

【问题讨论】:

    标签: c semaphore


    【解决方案1】:

    您对信号量的使用不太正确。信号量旨在保护一个或多个共享资源,通常用信号量的计数来表示可用的资源数量。对于共享内存段,您只有一个资源(内存块),因此您应该使用计数为 1 的单个信号量来保护它。

    这个单一的信号量协调所有的客户端和服务器。客户端获取信号量,写入其命令,然后释放信号量。服务器获取此信号量,读取命令并执行所需的任何处理,将结果写回共享内存,然后释放信号量。

    但是,正如您所发现的,这并不能协调每个客户端。没有什么可以阻止客户端读取另一个客户端的响应。所以你可以在这里使用另一个信号量,它可以被认为是保护与服务器的“通信通道”。同样,这是一个单一的资源,所以它应该有一个计数为 1 的信号量。

    所以你的完整设计将使用 2 个信号量,看起来像:

    1. 从一个计数为 0 的共享内存信号量和一个计数为 1 的通道信号量开始。
    2. 服务器等待共享内存信号量。
    3. 客户端获取通道信号量,递减为 0。这会阻止所有其他客户端。
    4. 然后,同一个客户端写入共享内存段并递增该信号量,从而解除对服务器的阻塞。
    5. 客户端和服务器根据需要进行通信,根据需要获取和释放内存信号量。
    6. 客户端完成后,它会释放通道信号量,从而解除另一个客户端与服务器通信的阻塞。

    请注意,服务器从不获取通信通道信号量。这纯粹是为了协调两个或更多的客户。

    我还想指出,这个解决方案相当混乱。有很多活动部件,很多地方可能会出现僵局。这是人们为 IPC 使用管道、套接字和消息队列之类的东西的很大一部分原因。您无需担心锁,因为协调已融入到通信通道的设计中(默认情况下读/写阻塞),并且每个客户端都有与服务器的单独通信通道。如果您担心性能,您应该查看this SO answer,它表明各种 IPC 机制在 Linux 上的速度都差不多。您可能会在其他类型的系统上看到不同的结果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-13
      • 2020-03-22
      • 2012-11-14
      • 1970-01-01
      相关资源
      最近更新 更多