2016-04-03 12 views
1

私はpthreadsとシグナルハンドリングを初めて利用しています。プロデューサまたはコンシューマとしてpthreadsを作成するプロジェクトでは、xを永久に実行し、すべてのスレッドを終了したいメインは系統的に遅延キャンセル付きpthreadsを終了する

これを行うには、​​をシグナルハンドラでキャッチし、グローバルフラグを設定してスレッドを終了しようとしています。

私は以下のことを試みましたが、それが動作しているかどうかは不明ですし、思考のプロセスと実装に関するアドバイスが必要です。ここで

は、私はエラーチェックを省略し、で働いていますものです:

#include stdio, pthread, stdlib, semaphore, time, string, unistd, signal 

sem_t empty, full; 
pthread_mutex_t mutex; 
int flag = 0; 
void *producer(); 
void *consumer(); 
void sig_handler(int sig); 

int main(int argc, char *argv[]){ 

    signal(handler(SIGINT, sig_handler); 

    //init locks and semas 
    pthread_mutex_init(&mutex, NULL); 
    sem_init(&empty, 0, SOME_BUFFER_SIZE); 
    sem_init(&full, 0, 0); 

    pthread_t prod_threads[5]; //5 for example, can be any amount passed in 
    pthread_t cons_threads[3]; 

    //start up threads 
    for(i = 0; i < 5; i++) 
     pthread_create(&prod_threads[i], NULL, producer, NULL) 
    for(i = 0; i < 3; i++) 
     pthread_create(&cons_threads[i], NULL, consumer, NULL) 

    //join threads at end 
    for(i = 0; i < PROD; i++) 
    pthread_join(&prod_threads[i], NULL); 

    for(i = 0; i < CONS; i++) 
    pthread_join(&cons_threads[i], NULL); 

    sleep(4);//could be any amount of time 
    exit(EXIT_SUCCESS); 

} 
//not sure if I am going about this the right way 
void sig_handler(int sig){ 
    if(sig == SIGINT) 
    flag = 1; 

} 

void *producer(){ 
    while(1){ 
    sleep(x);//where x is some random time 

    //part I am concerned about: 
    if(flag) 
     exit(EXIT_SUCCESS); 
    //get locks and semaphore stuff 
    //enter crit section 
    //release locks, semaphore 
    } 
void *consumer(){ 
    while(1){ 
     sleep(x);//sleep some random time 

     //again not sure if this is right or not 
     if(flag) 
     exit(EXIT_SUCCESS); 
     //get locks 
     //enter crit 
     //release locks 
    } 



} 
} 

私のプログラムが正しく実行するようだ、私はちょうど私が正しくのpthreadとの信号を使用していますかどうかわからないんだけど、そこにいくつかのガイダンスをしたいと思います。あなたはより多くの完全なコードが必要な場合は、単にしかし、ドキュメントが提供@yano使用して、私は

おかげ

+0

'私は両方のスレッドを終了し、次に系統的な方法でメインにしたいと思っています。 –

+0

正直言って@MartinJamesなぜ私はまだ欲しいのか分かりませんが、最初にスレッドを終了したいです –

+2

実際に必要があっても、終了するようにメッセージをキューに入れて消費者を終了させるのが普通です自分自身。私は通常、NULLをキューに入れ、NULLを取得するコンシューマは、それをバックアップして終了します。それは、最後の消費者が「ポイズンピル」終了メッセージを解放する必要がなく、何人であろうと、すべての消費者を殺す。いいえ睡眠()、待っていない:) –

答えて

0

あなたは実行が適切と思わだと知っている、あなたはpthread_join()はほんの少しオフになっています。

の代わりに:あなたが必要

for(i = 0; i < PROD; i++) 
pthread_join(&prod_threads[i], NULL); 

for(i = 0; i < CONS; i++) 
pthread_join(&cons_threads[i], NULL); 

for(i = 0; i < PROD; i++) 
pthread_join(prod_threads[i], NULL); 

for(i = 0; i < CONS; i++) 
pthread_join(cons_threads[i], NULL); 

はアンパサンドに注意してください。これがあなたが探しているものであるかどうかは分かりませんが、私はそれが助けてくれることを願っています。

0

すべてのスレッドを終了し、その後メインを系統的に終了したいとします。

マーティン・ジェイムスが提案するように、ワーカー・スレッドに終了を知らせる特別なスレッド・メッセージをキューに入れてください。このメッセージをキューから削除してはなりません。そのため、すべてのワーカースレッドがメッセージを受信して​​終了する機会があります。

もう1つのポイントは、ワーカースレッドでexitを呼び出すべきではないということです。これは、この関数がプロセス全体を終了させ、元の目標を打ち負かすためです。スレッド機能からちょうどreturn

マルチスレッドアプリケーションでは、すべての信号を特定のスレッド(通常はメインスレッドがその候補になることが多い)で処理することをお勧めします。他のすべてのスレッドで受信すると予想される信号をブロックします。他のスレッドを作成する前に期待されるシグナルをブロックし、シグナルマスクを継承し、シグナルハンドリングスレッドでこれらのシグナルを非ブロック化する(例えば、余分なスレッドがすべて作成されたときなど)これは、プロセスの対象となる信号(例えば、SIGINT)がそのスレッドのいずれかに配信される可能性があるためですが、そのスレッドを特定のスレッドで処理する必要があるためです。詳細はSignal Generation and Deliveryを参照してください。

関連する問題