2012-01-26 2 views
1

리눅스의 폴더에서 에 대한 스레드를 사용하여 모든 파일과 디렉토리를 읽으려고합니다. 현재 디렉토리와 현재 디렉토리 트리에서 가장 높은 파일 크기 인 &을 얻습니다.스레드 응용 프로그램에서 파일 크기 읽기 오류 (Linux, pthreads)

기본 스레드는 기본 디렉토리 찾기 파일을 검색하고 디렉토리가 발견되면 새 스레드가 생성되어 스캔을 계속합니다.

이 시점에서 스레드는 마지막으로 생성 된 스레드가 끝날 때까지 조인합니다. (이 방법을 사용하는 것이 가장 좋은 방법은 아니지만 실습 일뿐입니다.)

문제는 프로그램이 잘못된 결과를 반환하고 그 이유를 모르겠습니다.

나는 응용 프로그램 테스트하기 위해 다음과 같은 파일 트리를 가지고 : 그것은 거대 나무 아래

 

    . (Debug folder under codelite project/workspace) 
    ├── [  4096] dir1 
    │ └── [   9] arch-dir1.txt 
    ├── [  4096] dir2 
    │ ├── [   27] arch-dir2.txt 
    │ └── [  29083] huge 
    ├── [  29053] direxp 
    ├── [  27048] direxp.o 
    └── [   68] direxp.o.d 

것은 당신이 direxp (이 프로그램)의 현재 디렉토리 아래에있는 가장 높은 파일 크기를 볼 수있는 가장 높은 파일 크기를

 

    dir: . 
    dir: .. 
    arch: direxp.o.d 
    max dir & tree set to: direxp.o.d size: 68 
    arch: direxp.o 
    max file dir set to: direxp.o size: 27048 
    arch: .d 
    arch: direxp 
    max file dir set to: direxp size: 29053 
    dir: dir1 
    th dir: . 
    th dir: .. 
    th arch: arch-dir1.txt thsize: 4096 
    max tree file set to: arch-dir1.txt thsize: 4096 
    dir: dir2 
    th dir: . 
    th dir: .. 
    th arch: arch-dir2.txt thsize: 4096 
    th arch: huge thsize: 4096 

    Highest current directory file: 
    direxp tam:29053 bytes. 

    Highest tree file: 
    arch-dir1.txt tam:4096 bytes. 

일 - 접두사 문자열이 다른 스레드에서 처리 된 데이터를 보여 바이너리를 실행

, 나는 다음과 같은 결과를 얻었다.

나는 readdir (주 스레드) 및 readdir_r (생성 된 스레드) 함수를 사용하여 디렉토리 항목을 읽습니다.

나는 이것이 문제가 될 수 있다고 생각했지만 나중에 모든 스레드에서 readdir_r을 호출하는 프로그램을 컴파일하고 잘못된 결과가 계속 나타납니다. 파일 크기가 잘못 반환 왜

정말 나는 왜 파일이 ​​디렉토리로 처리?

당신이 좀 도와 줄 수 있습니다. 내 파일 시스템의 기본 클러스터 크기의 4096 (이해가 안 돼요? 감사

주요 기능 코드

#include <iostream> 
#include <cstdio> 
#include <cstring> 
#include <cstdlib> 

#include <sys/types.h> 
#include <sys/stat.h> 
#include <dirent.h> 
#include <unistd.h> 
#include <pthread.h> 

using std::cout; 
using std::cin; 
using std::endl; 

#define MAX_PATH 255 

struct archivo 
{ 
char nombre[MAX_PATH+1]; 
off_t tam; 
}; 

// thread args 
struct thargs 
{ 
char nextdir[MAX_PATH+1]; // next dir 
void* (*pth)(void*); // pointer to thread function 
archivo* arch; // pointer to archivo 
}; 


pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; 


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

char target[MAX_PATH+1] = {0}; // directorio inicial 

archivo grande_dir ={{0}},grande_arbol = {{0}}; 


    // No params 
    if (argc < 2) 
    { 
     if (! getcwd(target,MAX_PATH)) 
     { 
      perror("Error en path:"); 
      exit(-1); 
     } 
    } 

    if (argc == 2) 
     strncpy(target,argv[1],MAX_PATH); 

    if (argc > 2) 
    { 
     perror("Num params incorrecto"); 
     exit(-2); 
    } 

    DIR* midir = NULL; 

    // try to open target dir 
    if (! (midir = opendir(target))) 
    { 
     perror("Error abriendo dir:"); 
     exit(-3); 
    } 


    dirent* direntry; 
    //dirent* rentry1 = NULL; 

    struct stat estado = {0}; // struct needed for desambiguation 

    bool primera = true; // control var to initialize the search 

    // read current dir contents    
    //while((readdir_r(midir,&direntry,&rentry1) == 0) && rentry1 ) 
    while((direntry = readdir(midir))) 
    { 

     stat(direntry->d_name,&estado); 

     // current entry it's a file 
     if (direntry->d_type == DT_REG) 
     { 

      cout << "arch: " << direntry->d_name << endl; 

      // init search to find the highest file 
      if (primera) 
      { 
        strncpy(grande_dir.nombre,direntry->d_name,MAX_PATH); 
       grande_dir.tam = estado.st_size; 

       strncpy(grande_arbol.nombre,direntry->d_name,MAX_PATH); 
       grande_arbol.tam = estado.st_size; 

       primera = false; 

       cout << "max dir & tree set to: " << direntry->d_name << " size: " << estado.st_size << endl; 
      } 

      // High file size 
      if (estado.st_size > grande_dir.tam) 
      { 
       pthread_mutex_lock(&lock); 

       strncpy(grande_dir.nombre,direntry->d_name,MAX_PATH); 
       grande_dir.tam = estado.st_size; 

       pthread_mutex_unlock(&lock); 

       cout << "max file dir set to: " << direntry->d_name << " size: " << estado.st_size << endl; 
      } 


     } 

     // current entry it's a directory 
     if (direntry->d_type == DT_DIR) 
     { 

      cout << "dir: " << direntry->d_name << endl; 

      // check not . or .. dir 
      if ((strcmp(direntry->d_name,".") != 0) && (strcmp(direntry->d_name,"..") != 0)) 
      { 

       thargs args = {{0}}; 

       pthread_t th1; 

       pthread_mutex_lock(&lock); 

       sprintf(args.nextdir,"%s/%s",target,direntry->d_name); 
       args.arch = &grande_arbol; 
       args.pth = &procesadir; 

       pthread_mutex_unlock(&lock); 

       // new thread creation 
       pthread_create(&th1,NULL,procesadir,&args); 

       // main thread waits th1 completion 
       pthread_join(th1, NULL); 
      } 
     } 

    } 

    closedir(midir); 

    pthread_mutex_destroy(&lock); 

    cout << endl << "Highest file in current directory file :" << endl 
     << grande_dir.nombre << " tam:" << grande_dir.tam 
     << " bytes." << endl;   

    cout << endl << "Highest file in tree:" << endl 
     << grande_arbol.nombre << " tam:" << grande_arbol.tam 
     << " bytes." << endl; 

return 0; 
} 

스레드 함수 코드

void* procesadir(void* args) 
{ 

thargs* myargs = reinterpret_cast<thargs*>(args); 

DIR* thdir = NULL; 

if ((thdir = opendir(myargs->nextdir))) 
{ 

dirent thentry; 
dirent* rentry = NULL; 
struct stat thstat = {0}; 

//while((thentry = readdir(thdir))) 
while((readdir_r(thdir,&thentry,&rentry) == 0) && rentry ) 
{ 

stat(thentry.d_name,&thstat); 

if (thentry.d_type == DT_REG) 
{ 

cout << " th arch: " << thentry.d_name << " thsize: " << thstat.st_size << endl; 

if (thstat.st_size > myargs->arch->tam) 
{ 
    pthread_mutex_lock(&lock); 

    memset(myargs->arch->nombre,0,MAX_PATH); 
    strncpy(myargs->arch->nombre,thentry.d_name,MAX_PATH); 
    myargs->arch->tam = thstat.st_size; 

    pthread_mutex_unlock(&lock); 

    cout << "max tree file set to: " << thentry.d_name << " thsize: " << thstat.st_size << endl; 
} 


} 

if (thentry.d_type == DT_DIR) 
{ 

if ((strcmp(thentry.d_name,".") != 0) && (strcmp(thentry.d_name,"..") != 0)) 
{ 

    thargs largs = {{0}}; 

    pthread_t th2; 

     sprintf(largs.nextdir,"%s/%s",myargs->nextdir,thentry.d_name); 
     largs.arch = myargs->arch; 
     largs.pth = myargs->pth; 

     // thread creation     
     pthread_create(&th2,NULL,procesadir,&args); 

     // current thread waits th2 completion 
     pthread_join(th2, NULL); 
    } 

    cout << " th dir: " << thentry.d_name << endl; 

    } 
} 


closedir(thdir); 

     else 
     perror("Error abriendo dir en thread:"); 

return 0; 
} 

답변

1

당신이 만들고있는 stat() 호출에서 반환 값을 확인하는 것이 좋습니다.

작업자 스레드에서 thentry.d_name이 잘 보이지만 작업 디렉토리와 관련된 경로 정보가 없으면 stat(thentry.d_name,&thstat);에 대한 호출이 실패합니다.

0

각 디렉토리를 검사하기 위해 별도의 스레드를 만드는 것을 권장하지 않습니다. 이 프로그램은 I/O 바인딩이므로 여러 스레드를 사용하여 더 빨리 실행되지 않습니다. 여러 스레드가 동시에 다른 위치에서 읽기 때문에 디스크가 많이 탐색되는 경우가 발생하므로 느린 속도로 실행됩니다.

단일 스레드를 사용하고 디렉토리 트리의 간단한 깊이 우선 또는 너비 우선 탐색을 수행하는 것이 좋습니다.

관련 문제