2

スレッドを使用して現在の作業ディレクトリの内容を出力するプログラムを c で作成しようとしています。現在、適切な数のファイルが印刷されていますが、一部のファイルは複数回繰り返されています。実行するたびに、どのファイルが繰り返され、何回ランダムに見えるか。クリティカル セクションと思われる部分にミューテックス ロックを使用しようとしましたが、成功しませんでした。

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

struct arg_struct
{
    struct dirent *current;
    struct stat buf;
};


void * mybackup (void *arguments)
{
    pthread_mutex_lock( &mutex );
    struct arg_struct *args = arguments;
    printf( "[THREAD %u] ", (unsigned int)pthread_self());
    printf( "%s ", args->current->d_name );
    printf( "(%lld bytes)\n", (long long) args->buf.st_size );
    total_bytes += args->buf.st_size;
    pthread_mutex_unlock( &mutex );
    return NULL;
}

int main (int argc, char **argv)
{
    if (argc == 1) //For part 1, when no cmd line argument is given
    {
        int children = 0;
        int thread, i;
        pthread_t tid[100];
        char * current_path = ".";
        DIR * dir = opendir((char*)current_path); //Opens the current directory
        if (dir == NULL)  //Detects failure to open directory
        {
            perror("opendir() Failed");
            return EXIT_FAILURE;
        }

        struct dirent *current;
        int rc = 0;


        while ((current = readdir(dir)) != NULL)
        {
            struct stat buf;
            char new[10000]; //Used to create the complete path name

            //Next few lines create the complete path name required for Stat()
            strcpy(new, current_path);
            strcat(new, "/");
            strcat(new, (char*)current->d_name);
            rc = stat(new, &buf);
            //rc = stat(current -> d_name, &buf);
            if (rc < 0) //Detects stat() failure
            {
                perror("stat() Failed");
                return 1;
            }
            else
            {
                if (S_ISREG(buf.st_mode)) //If directory entry is a regular file
                {
                    struct arg_struct args;
                    args.current = current;
                    args.buf = buf;
                    thread = pthread_create(&tid[children], NULL, mybackup, (void *)&args);
                    if ( thread != 0 )
                    {
                        perror( "MAIN: Could not create child thread" );
                    }
                    children++;
                }
            }
        }

        for (i = 0; i < children; i++)
        {
            pthread_join(tid[i], NULL);
        }
        printf("Total bytes: %lld\n", total_bytes);
    }

    return 0;
}
4

1 に答える 1

5
{
  struct arg_struct args;
  ...
  thread = pthread_create(&tid[children], NULL, mybackup, (void *)&args);

これは正しくありません。スレッド関数に渡す (スタックベースの) オブジェクトは、作成されたスレッドが何かを行う前に上書きされる可能性が非常に高くなります。

その構造体が必要にmallocなる (およびfreeing を処理する) か、各スレッドに 1 つを割り当てることができるように十分な大きさのそのような構造体の配列 (スタック上または静的) を使用する必要があります。

実際、その構造体を割り当てるだけでは十分ではなくdirent* current、ポインターとして渡すことはできません。必要なデータをそこからスレッドごとの構造体にコピーするか、readdir_r代わりに使用する必要があります (man ページの例を注意深く読んでください)。 )。

于 2012-11-10T18:44:23.727 に答える