2016-11-05 10 views
0

私は2/3スレッドを持つ基本プログラムを構築しようとしています。メインスレッド、シグナルスレッド、およびレシーバスレッド。私はメインスレッドがシグナルと受信スレッドの両方を開始するようにしています。シグナルスレッドは、10個のSIGUSR1シグナルを受信スレッドに送信し、グローバルカウンタを増加させることになっています。受信スレッドは、受信された各信号について自身のカウンタを増加させながら10個の信号を受信することになっている。Cとpthread_joinストールプログラムの信号受信スレッド

私が抱えている問題は、最後にスレッドを一緒に結合して、具体的には受信スレッドに参加することです。受信者のスレッドが完了していない(信号が欠落している可能性があります)ので、プログラムが停止してしまい、終了しないことが想定されます。おそらくこれが当てはまると思っていたので、シグナルプロセッサスレッドにwaitコマンドを導入して速度を落としましたが、何も変わっていませんでした。

pthread_join(受信者、NULL)をコメントアウトすると、プログラムは実行されますが、ほとんどの場合、1つの信号しか捕捉しません。これは、受信側のスレッドが実行に時間がかからないためです。 (受信者、NULL)をプログラムに残すと、19/20回は停止しますが、プログラムは10回の信号を返します。送信され、10が受信された。これは私にそれが先制と関係があると信じるように導くが、なぜそれが最初に失速するのか理解していない。

また、受信したカウンタが<である間に受信スレッドがスレッドを受信して​​いるだけです。10.理想的には、while(1)ループに入れておきたいですが、すべてを凍らせずにメインスレッドに戻します。

なぜ誰かがシグナルが欠落している理由/プログラムがフリーズしている理由を理解できたら、私は最も感謝します。私は受信機のための信号マスクを正しく設定していないとの疑いがありますが、私はそれをやろうとしています。コードは次のとおりです。

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

void *receivetest(void *args); 
void *signaltest(void *args); 


int received = 0; 
int sent = 0; 
pthread_t signaler; 
pthread_t receiver; 
sigset_t mask; 

int main(){ 

    //setting up the signal mask 
    sigemptyset(&mask); 
    sigaddset(&mask, SIGUSR1); 

    //creation of both threads 
    pthread_create(&receiver, NULL, receivetest, NULL); 
    pthread_create(&signaler, NULL, signaltest, NULL); 


    pthread_join(signaler, NULL); 
    pthread_join(receiver, NULL); 

    //printing results after joining them back 
    printf("I'm the main function\n"); 
    printf("Receieved: %d, sent: %d\n", received, sent); 


} 

void *signaltest(void *args){ 
    int i = 0; 
    for(i=0;i<10;i++){ //sends 10 signals to receiver thread 
     pthread_kill(receiver, SIGUSR1); 
     sent++; 
    } 
} 

void *receivetest(void *args){ 
    int c; //sigwait needs int 
    pthread_sigmask(SIG_BLOCK, &mask, NULL); //sets up the signal mask for this thread 
    while(received < 10){ //waits for 10 signals and increments receieved 
     sigwait(&mask, &c); 
     received++; 
    } 
} 
+1

あなたが実際にやろうとしていますか?なぜシグナルをスレッド間通信メカニズムとして使用しようとしていますか? –

+0

'pthread_sigmask(SIG_BLOCK、&mask、NULL);'は 'mask'で定義されたすべてのシグナルをブロックすることを意味します。これはメインスレッドに置かれ、メインスレッドに到達するシグナルはすべてシグナルハンドラに渡されます。これは、信号受信機が信号を処理しなかったことを意味する。それはそれらをブロックした。 – alvits

答えて

0

あなたはほぼ正しくなっています。メインスレッドからのシグナルをブロックして、新しいスレッドがシグナルを誤って処理するのを防ぐことをお勧めします。

pthread_sigmask()以降に作成されたスレッドは、sigmaskを継承します。最初のパラメータは、pthread_sigmask()に、2番目のパラメータにリストされている信号の処理方法を指示します。

この行pthread_sigmask(SIG_BLOCK, &mask, NULL)は、シグナルハンドラではなく、メインスレッドに配置する必要があります。元のコードも正常に動作しますが、シグナルが間違ったスレッドに送られた場合、プロセス全体が終了します。

さらに、送信側は受信側よりも高速に信号を送信しています。各反復の間に1秒間スリープすることにより、受信機は追いつくことができる。

私は自由をとり、あなたのコードを修正しました。送信者と受信者の中にいくつかのプリントを追加したので、あなたはそれが何をしているのか分かります。

#include <stdio.h> 
#include <pthread.h> 
#include <stdlib.h> 
#include <signal.h> 
#include <unistd.h> 

void receivetest(void); //function does not return anything 
void signaltest(void); // does not accept parameter either. 


int received = 0; 
int sent = 0; 
pthread_t signaler; 
pthread_t receiver; 
sigset_t mask; 

int main(){ 

    //setting up the signal mask 
    sigemptyset(&mask); 
    sigaddset(&mask, SIGUSR1); 
    pthread_sigmask(SIG_BLOCK, &mask, NULL); //sets up the signal mask for this thread 

    //creation of both threads 
    pthread_create(&receiver, NULL, (void *)receivetest, NULL); 
    pthread_create(&signaler, NULL, (void *)signaltest, NULL); 


    pthread_join(signaler, NULL); 
    pthread_join(receiver, NULL); 

    //printing results after joining them back 
    printf("I'm the main function\n"); 
    printf("Receieved: %d, sent: %d\n", received, sent); 
    return 0; 

} 

void signaltest(void){ 
    int i = 0; 
    for(i=0;i<10;i++){ //sends 10 signals to receiver thread 
     printf("Sending signal\n"); 
     pthread_kill(receiver, SIGUSR1); 
     sleep(1); // Don't send signals too fast 
     sent++; 
    } 
} 

void receivetest(void){ 
    int c; //sigwait needs int 
    while(received < 10){ //waits for 10 signals and increments receieved 
     sigwait(&mask, &c); 
     printf("Signal received\n"); 
     received++; 
    } 
} 

出力:

Sending signal 
Signal received 
Sending signal 
Signal received 
Sending signal 
Signal received 
Sending signal 
Signal received 
Sending signal 
Signal received 
Sending signal 
Signal received 
Sending signal 
Signal received 
Sending signal 
Signal received 
Sending signal 
Signal received 
Sending signal 
Signal received 
I'm the main function 
Receieved: 10, sent: 10 
+0

私は、ありがとうございます。私はまだシグママスクを設定することについて混乱しています。なぜシグママスクを設定するのがマスクを開くのではなくマスクの信号をブロックするのですか?また、もし私が2つのシグナルを持っていたら、どうすればいいのですか?私はmain関数で両方のシグナルをブロックし、それから単にreceiver_aにシグナルを待ってからreceiver_bだけbシグナルを待つようにしますか?その場合、sigwaitマスクはそれぞれどのようにすべきですか? – bittersweets

+0

@bittersweets - 'pthread_sigmask'は最初のパラメータが何をするかを指示します。 'SIG_BLOCK'は、2番目のパラメータにリストされたシグナルをブロックするよう指示します。 'pthread_sigmask()'の後に作成されたスレッドは、それを継承します。すべてのスレッドをシグナルから保護し、シグナルを処理するスレッドを指定するのが通例です。 – alvits

+0

@bittersweets - あなたのフォローアップの質問のために、各シグナルハンドラは、自分自身が指定するシグナルを待つ必要があります。各ハンドラへのローカル変数として 'mask'を定義する方が良いでしょう。 – alvits

1

信号はちょうどそのようには機能しません。同じ信号がすでに保留中のときにスレッドが信号を受信すると、何も起こりません。信号ではなく、適切なスレッド間通信方法を使用してください。

+0

これはクラスプロジェクトのためのものです。我々は信号を使うように言われている。 (プロジェクト自体は、私が尋ねているプログラムとは異なりますが、シグナルジェネレータスレッドとシグナルハンドラスレッドを使用すると言います)。 受信者に送信された信号がないために、プログラムがフリーズしている理由が考えられますか?私はシグナルマスクを正しく設定しましたか? – bittersweets

+0

内部カウンタが10に達する前に信号を10回以上送信しなければならない場合があります。信号はトランザクションメッセージングメカニズムにはなりませんでした。 – sturcotte06

+0

ありがとうございます。私は送った金額を上げようとしましたが、実際にそれを捕まえることはできません。 (それでもまだ多くのことを逃していますが、100を送信するとまだ時間の凍結がありますが、それは信号がうまくいかない理由だと思います。セマフォを使用することで、私はそれをより良く同期できますが、プロジェクトのためにやらなければならない...) とにかく、David Schwartzとsturcotte06ありがとうございました – bittersweets

関連する問題