1

2つの異なる端末で実行中のプロセス(サーバーとクライアント)を処理する必要があります。クライアントはユーザー入力を読み取り、それをファイル(hello.txt)に保存し、SIGUSR1に信号を送り、スリープします。次に、サーバーはウェイクアップし、ファイル(hello.txt)を読み取り、それを印刷し、クライアントに動作したことを通知してからスリープします。次に、クライアントはウェイクアップし、成功したことを出力して、別のユーザー入力を待ちます。

後でそれ以上のものがありますが、これが私が現在達成しようとしているすべてです。2つの別々の無関係なプロセス間でsigactionとSIGUSR1を使用した例を見つけるのに苦労しました。これが私がこれまでに持っているコードです:

server.c

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

volatile sig_atomic_t myFlag = 0;
static void myHandler(int);
struct sigaction newAction, oldAction;


int main(int argc, char* argv[])
{
    //setup signal stuff
    sigset_t zeromask;
    sigemptyset(&newAction.sa_mask);
    sigemptyset (&oldAction.sa_mask);
    sigemptyset(&zeromask);
    newAction.sa_flags = 0;
    newAction.sa_handler = myHandler;
    sigaddset (&newAction.sa_mask, SIGUSR1);
    if ( sigaction(SIGUSR1, &newAction, &oldAction))
            return;

    for ( ; ; ) {
            //Loop
            //This is so I can manually enter the pid into the client 
            printf("%d\n",getpid());
            while(myFlag == 0)
                    sigsuspend (&zeromask);
            myFlag = 0;
            printf("Got signal, process it\n");

    //signal occured process it
    }

    sigprocmask (SIG_SETMASK, &oldAction.sa_mask, NULL);
    exit(0);
    }

static void myHandler(int sigNo) {
    myFlag = 1;

    printf("finally made it");
    sigprocmask (SIG_BLOCK, &newAction.sa_mask, &oldAction.sa_mask);
    return;
}

client.c

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

volatile sig_atomic_t myFlag = 0;
static void myHandler(int);
struct sigaction newAction, oldAction;


int main(int argc, char* argv[])
{
    printf("begin\n");
    //Signal stuff 
    sigset_t zeromask;
    sigemptyset(&newAction.sa_mask);
    newAction.sa_flags = 0;
    newAction.sa_handler = myHandler;
    sigemptyset (&oldAction.sa_mask);
    sigemptyset(&zeromask);
    sigaddset (&newAction.sa_mask, SIGUSR1);
    if ( sigaction(SIGUSR1, &newAction, &oldAction))
            return;
    sigprocmask (SIG_BLOCK, &newAction.sa_mask, &oldAction.sa_mask);

    //loop
    for ( ; ; ) {
            printf("This is where you would get user input\n");
            //Signal Server
            //For now I just manually enter the pid that was printed out when I ran server.c. This does not work and I do not think it is the right thing to do 
            kill(27514,SIGUSR1);
            //loop while waiting for server to respond
            while(myFlag == 0)
                    sigsuspend (&zeromask);

            myFlag = 0;
            printf("this is where you would process return signal\n");
    //signal occured process it
    }

    sigprocmask (SIG_SETMASK, &oldAction.sa_mask, NULL);
    exit(0);
    }

    static void myHandler(int sigNo) {
          myFlag = 1;
          sigprocmask (SIG_BLOCK, &newAction.sa_mask, &oldAction.sa_mask);
          return;
    }

今のところ、このコードが実行するのは、クライアントからサーバーに信号を送ることだけです。そこから残りを実装します。しかし、これはうまくいかず、私には理解できないようです。

killは、SIGUSR1を実装するために使用する正しいコマンドですか?クライアントとサーバーが通信するために、それぞれのPIDを知る必要がありますか?私は完全に間違ったことをしているだけですか?

4

2 に答える 2

2

あなたは実際に何が起こっているのかを示していませんが、あなたの質問に答えるために:

「SIGUSR1を実装するために使用する正しいコマンドをkillしますか?」はい。

「クライアントとサーバーが通信するには、各クライアントとサーバーのPIDを知る必要がありますか?」はい。

「私は完全に間違ったことをしているだけですか?」はい。

シグナルの使用に関する主な問題は、1)プログラムの実行中にいつでも到着し、2)特定の時間にのみ処理する準備ができていることです。

上記のコードは、シグナルがsigsuspend()にあり、待機している場合にのみ、シグナルを正しく処理します。これは常に真実ではありません!ループの他の部分にいるとき、つまり、kill()を他のプロセスに送信するとき、再びsigsuspendに到達する前に、他のプロセスのkill()が戻ってきたらどうなるかを考えてください...あなたは勝ちました信号を待つ必要はありません、そしてそれは行き来します。あなたの実装は信頼できません。

より信頼性の高い実装は、プロセス間でソケット接続を使用することです。このような接続を介して、信号またはデータ自体を通信することができます。実際、これを行うには多くの方法があります。http://en.wikipedia.org/wiki/Inter-process_communicationを参照してください(上記のPOSIXインターフェースを使用しているようです)。

結果として、信号は非同期であり、任意のプログラムのフローを中断し、プログラムに固有であるため、常に準備ができているとは限りません。信号を見逃すと、信号は失われます。ソケット(またはパイプまたは実際のファイル記述子を持つその他のもの)を使用すると、データ(シグナル)により、単に飛ぶのではなく、select()またはpoll()が返されます。

于 2013-02-19T20:57:02.007 に答える
0

これは、クライアントとサーバー間で通信するための最良の方法ではありません。名前付きパイプを確認する必要があります。

ここでの主な問題はmyFlag、クライアントとサーバーの間で共有されていないことです。2つのプログラムは独立したメモリで実行されています。そのように通信したい場合は、共有メモリを使用する必要があります。(これは、名前付きパイプの別の代替手段になります。)

お気づきのように、もう1つの問題は、クライアントがサーバーのpidを検出する簡単な方法がないことです。サーバーがそのpidを既知の名前のファイルに保存することは可能ですが(管理タスクを簡単にするために多くの場合これを行います)、これを行うための良い方法は実際にはありませんが、それは多くの可能性を生み出します競合状態; それは決して信頼できるメカニズムではありません。この場合も、名前付きパイプ(または名前付き共有メモリセグメント)は、同じホスト上のプロセス間のプロセス間通信に信頼できるメカニズムを提供します。

クライアントとサーバーが異なるマシンで実行されている可能性がある場合(非常に一般的な使用例)、おそらく単一のホストでも機能するソケットを使用することをお勧めします。

于 2013-02-19T20:53:00.100 に答える