2012-01-26 21 views
1

Linuxのフォルダにあるすべてのファイルとディレクトリを のスレッドで読み取ろうとしています。現在のディレクトリと現在のディレクトリツリーの下に最大ファイルサイズ&を取得します。スレッドアプリケーション(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バウンドなので、複数のスレッドを使用しても高速に実行することはできません。何らかのスレッドが複数の場所から同時に読み込まれているため、ディスクが頻繁に検索されるため、実行速度が遅くなります。

単一のスレッドを使用して、ディレクトリツリーの単純な深さ優先または幅優先横断を行う方がよいでしょう。

関連する問題