2017-12-29 57 views
0

私はクライアントプログラムでサーバーを実装しています。通信は共有メモリと連動します。共通のリソースへのアクセスを制御するために、私はセマフォを使用しています。クライアントがサーバーに対して新規である場合、サーバーはクライアントのIDを生成します。クライアントはIDを保存し、それ以降のリクエストでこのIDを送信します。 私はサーバーとクライアント間の通信に次のコードを使用しています。このソリューションは、1つのサーバーと1つのクライアントに対してのみ機能します。どのように3つのセマフォを使用するサーバークライアントアーキテクチャの共有メモリ

サーバー:

#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); 

サーバが動作するはずです/ 1クライアント、より多くを管理します。私はこれを3番目のセマフォで解決できると思ったが、デッドロックの問題に遭遇しているか、クライアントが他のクライアントの結果を処理している。

第三セマフォと私のソリューションは、次のようになります。

サーバー:

クライアント

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

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

がどのように私はこの問題を解決することができますか?

答えて

0

あなたのセマフォの使用法は正しくありません。セマフォは、通常1つまたは複数の共有リソースを保護するように設計されています。通常は、リソースの数を表すセマフォの数がになります。共有メモリセグメントの場合は、単一のリソース(メモリブロック)しか持たないので、1つのセマフォを使用してそれを保護する必要があります。

この単一のセマフォは、すべてのクライアントとサーバーを調整します。クライアントはセマフォを取得し、そのコマンドを書き込んだ後、セマフォを解放します。サーバはこのセマフォを取得し、コマンドを読み込み、必要な処理を行い、その結果を共有メモリに書き戻し、セマフォを解放します。

しかし、あなたが発見したように、これは各クライアントを調整しません。クライアントが別のクライアントの応答を読み取ることを妨げるものは何もありません。したがって、ここで別のセマフォを使用することもできます。これは、サーバーとの "通信チャネル"を保護することと考えることができます。共有メモリセマフォと

  1. スタート:それはだからあなたの完全なデザインが2つのセマフォを使用して、次のようになります。1.

    の数とセマフォを持っている必要がありますので繰り返しますが、これは、単一のリソースでありますカウント0、チャンネル1のセマフォを含む。

  2. サーバは共有メモリセマフォを待つ。
  3. クライアントはチャネルセマフォを取得し、0にデクリメントします。これにより、他のすべてのクライアントがブロックされます。
  4. 同じクライアントが共有メモリセグメントに書き込み、そのセマフォをインクリメントし、サーバーのブロックを解除します。
  5. クライアントとサーバーは必要に応じて通信し、必要に応じてメモリセマフォを取得して解放します。
  6. クライアントが完了すると、チャネルセマフォを解放し、別のクライアントのブロックを解除してサーバーと通信します。

サーバは決して通信チャネルセマフォを取得しないことに注意してください。純粋に2人以上のクライアントを調整することです。

私は、この解決法はかなり面倒だと指摘したいと思います。多くの可動部品があり、デッドロックの可能性がある場所がたくさんあります。これは、人々がIPCのパイプ、ソケット、メッセージキューのようなものを使う理由の大きな部分です。コーディネーションは通信チャネルの設計(既定では読み取り/書き込みブロック)に組み込まれ、各クライアントはサーバーと別個の通信チャネルを持つため、ロックについては心配する必要はありません。パフォーマンスが心配な方は、this SO answerをチェックして、Linux上でさまざまなIPCメカニズムがほぼ同じスピードになっていることを確認する必要があります。別の種類のシステムで異なる結果が表示されることがあります。

関連する問題