2017-12-29 41 views
0

클라이언트 프로그램이있는 서버를 구현하고 있습니다. 통신은 공유 메모리와 작동합니다. 공통 리소스에 대한 액세스를 제어하기 위해 세마포를 사용합니다. 클라이언트가 서버를 처음 사용하는 경우 서버는 클라이언트에 대한 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);

가 어떻게이 문제를 해결할 수 있습니까?

답변

0

세마포어 사용이 적절하지 않습니다. 세마포어는 보통 하나 이상의 공유 리소스를 보호하기 위해 설계되었으며 대개 리소스의 수를 나타내는 세마포어 카운트가입니다. 공유 메모리 세그먼트의 경우 단일 리소스 (메모리 블록) 만 있기 때문에 보호를 위해 카운트 1의 단일 세마포어를 사용해야합니다.

이 단일 세마포는 모든 클라이언트와 서버를 조정합니다. 클라이언트는 세마포어를 획득하고 명령을 쓰고 세마포어를 해제합니다. 서버는이 세마포어를 획득하고 명령을 읽고 필요한 처리를 수행하며 결과를 공유 메모리에 다시 쓰고 세마포어를 해제합니다.

그러나 발견 한대로 각 클라이언트를 조정하지는 않습니다. 클라이언트가 다른 클라이언트의 응답을 읽지 못하게 할 수는 없습니다. 따라서 여기에 또 다른 세마포어를 사용할 수 있습니다.이 세마포어는 서버와의 "통신 채널"을 보호하는 것으로 생각할 수 있습니다. 공유 메모리 세마포어

  1. 시작 : 그것은 1.

    의 수와 세마포어를해야한다 그래서 전체 디자인이 세마포어을 사용하고, 같은 모양 때문에 다시, 이것은 하나의 자원이되며, 카운트가 0이고 채널 세마포어가 1입니다.

  2. 서버는 공유 메모리 세마포어를 기다립니다.
  3. 클라이언트가 채널 세마포를 획득하고 0으로 감소합니다. 그러면 다른 모든 클라이언트가 차단됩니다.
  4. 그런 다음 동일한 클라이언트가 공유 메모리 세그먼트에 쓰고 해당 세마포어를 증가시켜 서버의 차단을 해제합니다.
  5. 클라이언트와 서버는 필요에 따라 통신하며 원하는대로 메모리 세마포어를 획득하고 해제합니다.
  6. 클라이언트가 완료되면 채널 세마포를 해제하고 다른 클라이언트의 차단을 해제하여 서버와 통신합니다.

서버는 결코 통신 채널 세마포어를 얻지 않습니다. 그것은 순전히 2 명 이상의 클라이언트를 조정하는 것입니다.

이 솔루션은 상당히 엉망이라고 지적하고 싶습니다. 움직이는 부분이 많고 교착 상태가 발생할 가능성이있는 곳이 많습니다. 이것은 사람들이 IPC를 위해 파이프, 소켓 및 메시지 대기열과 같은 것을 사용하는 이유 중 상당 부분을 차지합니다. 통신 채널 설계 (기본적으로 읽기/쓰기 블록)로 조정이 이루어지기 때문에 잠금에 대해 걱정할 필요가 없으며 각 클라이언트는 서버와 별도의 통신 채널을 갖습니다. 성능이 걱정된다면 this SO answer에서 다양한 IPC 메커니즘이 모두 Linux에서 거의 동일한 속도임을 확인해야합니다. 다른 유형의 시스템에서 다른 결과가 나타날 수 있습니다.