1

私はミューテックスを勉強していて、運動で立ち往生しています。特定のディレクトリ内のファイルごとに、そのファイルを読み取ってその内容を表示するためのスレッドを作成する必要があります(順序が正しくない場合は問題ありません)。

これまでのところ、スレッドはこの関数を実行しています。

void * reader_thread (void * arg)
{   

    char * file_path = (char*)arg;
    FILE * f;
    char temp[20];
    int value;

    f=fopen(file_path, "r");
    printf("Opened %s.\n",file_path);

    while (fscanf(f, "%s",temp)!=EOF)
        if (!get_number (temp, &value)) /*Gets int value from given string (if numeric)*/
             printf("Thread %lu -> %s: %d\n", pthread_self(), file_path, value );

    fclose(f);
    pthread_exit(NULL);

}

DIR以前に。によって作成されたポインタを受け取る関数によって呼び出されているopendir()。(ここでは、よりクリーンにするためにいくつかのエラーチェックを省略しましたが、エラーはまったく発生しません。)

int readfiles (DIR * dir, char * path)
{

    struct dirent * temp = NULL;        
    char  * file_path;
    pthread_t thList [MAX_THREADS];
    int nThreads=0, i;

    memset(thList, 0, sizeof(pthread_t)*MAX_THREADS);
    file_path=malloc((257+strlen(path))*sizeof(char));      

    while((temp = readdir (dir))!=NULL && nThreads<MAX_THREADS) /*Reads files from dir*/
    {

        if (temp->d_name[0] != '.')                     /*Ignores the ones beggining with '.'*/
        {   
            get_file_path(path, temp->d_name, file_path);   /*Computes rute (overwritten every iteration)*/
            printf("Got %s.\n", file_path);
            pthread_create(&thList[nThreads], NULL, reader_thread, (void * )file_path)  

            nThreads++; 
        }       
    }

    printf("readdir: %s\n", strerror (errno ));     /*Just in case*/

    for (i=0; i<nThreads ; i++)
        pthread_join(thList[i], NULL)

    if (file_path)
        free(file_path);

    return 0;

}

ここでの私の問題は、パスは完全に計算されますが、スレッドが正しい引数を受け取っていないように見えることです。それらはすべて同じファイルを読み取ります。これは私が得る出力です:

Got test/testB.
Got test/testA.
readdir: Success
Opened test/testA.
Thread 139976911939328 -> test/testA: 3536
Thread 139976911939328 -> test/testA: 37
Thread 139976911939328 -> test/testA: -38
Thread 139976911939328 -> test/testA: -985
Opened test/testA.
Thread 139976903546624 -> test/testA: 3536
Thread 139976903546624 -> test/testA: 37
Thread 139976903546624 -> test/testA: -38
Thread 139976903546624 -> test/testA: -985

次のスレッドが始まる前にスレッドに参加すれば、問題なく動作します。ですから、どこかにクリティカルセクションがあると思いますが、それを見つける方法がよくわかりません。スレッド関数全体をミューテックスしてみました:

void * reader_thread (void * arg)
{   

    pthread_mutex_lock(&mutex_file);
    /*...*/
    pthread_mutex_unlock(&mutex_file);

}

また、2番目の関数のwhileループをミュートします。同時に両方でも。しかし、それは決して機能しません。ちなみに、mutex_fileはグローバル変数であり、で初期化さpthread_mutex_init()main()ます。

何が間違っているのかよくわからないので、これについてアドバイスをいただければ幸いです。ミューテックスとSystemVセマフォは私にとって少し難しいと感じているので、いくつかの良い参考資料や本もいただければ幸いです。

どうもありがとうございます。

4

2 に答える 2

3

さて、ファイル パスとまったく同じポインタを両方のスレッドに渡しています。その結果、同じ文字列からファイル名を読み取り、同じファイルを読み取ることになります。実際には、競合状態があるため、ここでは少し幸運です。文字列ポインターfile_pathから読み取るスレッドを起動している間に文字列ポインターの内容を更新します。変更中です。あなたがしなければならないことは、各スレッドに個別に引数を割り当て (つまり、ループmalloc内の呼び出しと関連するロジック)、スレッドが終了したらそれらの引数を解放することです。while

于 2012-11-09T20:53:48.270 に答える
3

すべてのスレッドに同じ file_path バッファを使用しているように見えますが、次の名前で何度もロードしています。スレッドごとに新しい文字列を割り当て、使用後に各スレッドで文字列を削除する必要があります。

編集

すでにスレッドの配列があるので、対応するスレッドのファイル名を保持する char[] の並列配列を作成するだけです。これにより、malloc/free が回避されます。

于 2012-11-09T20:54:56.463 に答える