0

私の意図は、マルチスレッドを使用して2つのファイルを転置することです。しかし、以下のプログラムは私にセグメンテーション違反を与えています。

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


void *a_to_temp( void *filea);
void copyFile( FILE *in, FILE *out );
void *temp_to_b( void *fileb);
void *b_to_a(void *ab);

struct files{
    char a[80];
    char b[80];
} ab;

pthread_mutex_t temptob     = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t btoa        = PTHREAD_MUTEX_INITIALIZER;

main(int argc, char **argv)
{
    fprintf(stderr, "in main");

    pthread_t thread1, thread2, thread3;
    strcpy( ab.a, argv[1]);
    strcpy(ab.b, argv[2]);

    int  iret1, iret2, iret3;

    pthread_mutex_lock( &temptob );
    pthread_mutex_lock( &btoa );

    iret1 = pthread_create( &thread1, NULL, a_to_temp, (void*) &argv[1]);

    iret2 = pthread_create( &thread2, NULL, b_to_a, (void*) &ab);

    iret3 = pthread_create( &thread3, NULL, temp_to_b, (void*) &argv[2]);


    pthread_join( thread1, NULL);
    pthread_join( thread2, NULL);
    pthread_join( thread3, NULL);

    exit(0);
}


void *a_to_temp( void *filea) {
    FILE *a = fopen((char *)filea, "r");    
    FILE *f = fopen( "temp", "w");
    copyFile( a , f);
    fclose(f);
    fclose( a); 
    pthread_mutex_unlock( &temptob );
}

void *temp_to_b( void *fileb) {
    pthread_mutex_lock( &temptob );
    FILE *b = fopen((char *)fileb, "r");
    FILE *f = fopen( "temp", "r");
    copyFile( f, b);
    fclose(f);  
    pthread_mutex_unlock( &btoa );
}

void *b_to_a(void *ab) {
    pthread_mutex_lock( &btoa );
    FILE *a = fopen(((struct files *) ab)->a, "w"); //
    FILE *b = fopen(((struct files *) ab)->b, "r");//
    fprintf(stderr, "c files opened");
    copyFile( b, a);
    fclose(a);
    fclose(b);
}

void copyFile( FILE *in, FILE *out) {
    char ch;
    while(!feof(in)) {
        ch = getc(in);  
        if(!feof(in)) putc(ch, out);            
    }
}

値を出力して、main関数の最後までコードをテストしました。エラーは関数の1つにあるはずだと思います。

4

3 に答える 3

3

コードの問題の1つは、ミューテックスを1つのスレッドでロックし、許可されていない別のスレッドでロック解除していることです。

ミューテックスを所有していないスレッドでミューテックスのロックを解除しようとすると、未定義の動作が発生する可能性があります。

たとえば、pthread_mutex_lock( &temptob );はメインスレッドにありますがpthread_mutex_unlock( &temptob );、はa_to_tempにあります。

于 2012-05-22T11:30:39.643 に答える
2

である関数に渡し&argv[1]て、それを。であるかのように使用しようとします。と機能についても同様です。これは幸福のレシピではありません。コアダンプは非常に妥当な応答です。a_to_temp()char **char *&argv[2]temp_to_b()

&最も簡単な修正は、pthread_create()呼び出しをドロップすることです。char **別の方法は、呼び出された関数でを処理することです。

注:これは、間違ったデータへのアクセスによって引き起こされたコアダンプを修正するだけです。コードにもアルゴリズムの問​​題がある可能性があり、正しい同期が行われるようにします。そして、ここでスレッドを使用することでパフォーマンスが向上するかどうかは議論の余地があります。確かに、おそらくありません。しかし、それはおそらく、スレッド化されたコードを完全に機能させるという演習のポイントに正接していると思われます。


スレッドをシリアル化する方法を教えていただけますか。役に立たないように見えるミューテックスを使用しようとしていました。

1つの項目は、すべてのシステムコールでエラーチェックを確実に行うことです。現時点では、すべてが機能すると想定しています。ただし、ジェイは「ミューテックスをロックするスレッドもロックを解除する必要がある」という正しい方向に進んでいると思います。pthread_cond_init()ミューテックスではなく、ファイルへのアクセスを制御する1つまたは2つの条件(など)が必要になる場合があります。

于 2012-05-22T11:34:37.893 に答える
1

介入して申し訳ありませんが、本当に達成したいのは必ずしも相互排除ではなく、操作のシリアル化です(つまり、操作の順序付け:最初:copy_a_to_temp; 2番目:copy_b_to_a; 3番目:copy_temp_to_b)。上記の答えは、同じスレッドによるミューテックスのロックとロック解除について正しいです。ただし、順序付け(または、より正確には、別のスレッドがタスクを完了するまでスレッドを強制的に待機させる)は、実際にはミューテックスの仕事ではなく、モニター/条件変数(または、より複雑な方法で、セマフォはモニターを実装できるため、セマフォ)。スレッドを強制するには(たとえば、copy_b_to_aはしてはいけませcopy_a_to_tempが作業を完了する前に発生します)、pthread_cond_waitを使用する必要があります。pthread_cond_waitの使用方法を公開する質問については、この質問を参照してください。* my *スレッドがウェイクアップされることを保証するために、(pthread_cond_signalを介して)pthread_cond_broadcastを使用する必要がありますか?

于 2012-06-12T20:33:20.733 に答える