2012-11-09 4 views
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); 

} 

는 이전에 opendir()에 의해 생성 된 DIR 포인터를 수신하는 기능에 의해 호출된다. (나는 그것이 청소기 만들기 위해 여기에 어떤 에러 체크를 생략했지만, 나는 전혀 오류가 발생하지 않습니다.)

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 

: 이것은 내가 얻을 출력됩니다. 그래서 저는 어딘가에 비판적인 섹션이 있다고 가정합니다. 그러나 그것을 찾는 법을 정말로 모르겠습니다. 나는 전체 스레드 함수를 mutexing하려고 시도했다.

void * reader_thread (void * arg) 
{ 

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

} 

또한 두 번째 함수에서 while 루프를 뮤텍스 처리한다. 동시에 둘 다. 그러나 그것은 어떤 식 으로든 작동하지 않을 것입니다. 그런데 mutex_file은 pthread_mutex_init()에 의해 초기화 된 main()에있는 전역 변수입니다.

정말로 내가 뭘 잘못하고 있는지 알지 못해서 나는 이것에 대한 조언을 해주실 것입니다. 뮤텍스와 System V 세마포어가 나에게 조금 어려움을 느끼기 때문에 나는 훌륭한 참고서 나 책을 읽어 주셔서 감사하겠습니다.

대단히 감사합니다.

답변

3

글쎄, 파일 경로와 정확히 같은 포인터를 두 스레드에 전달하고 있습니다. 결과적으로 동일한 문자열에서 파일 이름을 읽고 동일한 파일을 읽습니다. 실제로, 당신은 현실적으로 당신이 경쟁 조건을 가지고 있기 때문에 약간 운이 좋습니다 - 문자열 포인터의 내용을 file_path으로 업데이트하면서 해당 포인터를 읽는 스레드를 실행하는 동안 해당 메모리를 읽는 스레드로 끝날 수 있습니다. 그것은 바뀌고있다. 당신이해야 할 일은 각각의 스레드에 대해 개별적으로 인수를 할당하는 것입니다 (즉, malloc 및 관련 논리를 while 루프에 호출). 스레드가 종료되면 이러한 인수를 해제하십시오.

+0

대단히 감사합니다. 사실, 필자가 언급 한 경쟁 조건은 file_path가 모든 반복을 변경하기 때문에 발생했습니다. 나는 mutex를 사용하여 스레드 함수에서'get_file_path()'전에 잠금을 설정하고'fclose (f);의 바로 전에 잠금을 해제했습니다. 일하는 것 같습니다. 고맙습니다!! – Serge

3

모든 스레드에 대해 동일한 file_path 버퍼를 사용하고있는 것처럼 보입니다. 다음 파일 이름을 반복해서로드하는 것처럼 보입니다. 각 스레드에 대해 새 문자열을 할당하고 각 스레드에서 사용 후 문자열을 삭제해야합니다. 이미 스레드의 배열을 가지고 있기 때문에

편집

, 당신은 [], 각각 해당 스레드에 대한 파일 이름을 잡고 문자의 병렬 배열을 만들 수 있습니다. 이렇게하면 malloc/free를 피할 수 있습니다.

관련 문제