2011-01-10 4 views
2

Я смотрел, как написать многопоточный код C++ для сканирования каталога и получить список всех файлов под ним. Я написал один многопоточный код, который можно сделать и под кодом, который может это сделать.C++ Многопоточный код сканирования каталога

#include <sys/types.h> 
#include <dirent.h> 
#include <errno.h> 
#include <vector> 
#include <string> 
#include <iostream> 
#include <sys/stat.h> /* for stat() */ 


using namespace std; 
int isDir(string path) 
; 

/*function... might want it in some class?*/ 
int getdir (string dir, vector<string> &dirlist, vector<string> &fileList) 
{ 
    DIR *dp; 
    struct dirent *dirp, *dirFp ; 
    if((dp = opendir(dir.c_str())) == NULL) { 
     cout << "Error(" << errno << ") opening " << dir << endl; 
     return errno; 
    } 

    while ((dirp = readdir(dp)) != NULL) { 
     if (strcmp (dirp->d_name, ".") != 0 && strcmp(dirp->d_name, "..") != 0) { 
      //dirlist.push_back(string(dirp->d_name)); 

      string Tmp = dir.c_str()+ string("/") + string(dirp->d_name); 
      if(isDir(Tmp)) { 
      //if(isDir(string(dir.c_str() + dirp->d_name))) { 
       dirlist.push_back(Tmp); 
       getdir(Tmp,dirlist,fileList); 
      } else { 
    //    cout << "Files :"<<dirp->d_name << endl; 
       fileList.push_back(string(Tmp)); 
      } 

     } 
    } 
    closedir(dp); 
    return 0; 
} 

int isDir(string path) 
{ 
    struct stat stat_buf; 
    stat(path.c_str(), &stat_buf); 
    int is_dir = S_ISDIR(stat_buf.st_mode); 
// cout <<"isDir :Path "<<path.c_str()<<endl; 
    return (is_dir ? 1: 0); 
} 

int main() 
{ 
    string dir = string("/test1/mfs"); 
    vector<string> dirlist = vector<string>(); 
    vector<string> fileList = vector<string>(); 

    getdir(dir,dirlist,fileList); 
#if 0 
    for (unsigned int i = 0;i < dirlist.size();i++) { 
     cout << "Dir LIst" <<dirlist[i] << endl; 
     //string dirF = dir + "/" + dirlist[i]; 
     //getdir(dirF,fileList); 
    } 
#endif 
    for (unsigned int i = 0; i < fileList.size(); i++) 
     cout << "Files :"<<fileList[i]<< endl; 
    return 0; 
} 

Теперь проблема заключается в том, что она однопоточная, и мне нужно сканировать примерно 8000 каталогов, под которыми может присутствовать файл. Поэтому я не понимаю, как это сделать, поскольку количество каталогов может меняться, поскольку оно определяется матрицей размерности N.

Любая помощь в этом отношении будет отличной. Заранее спасибо.

+1

Я не совсем уверен, что такое матрица N-размерности, о которой вы говорите. Но чтобы ответить на ваш вопрос, вы в конечном счете должны сделать параллельный поиск по глубине. Я полагаю, вы знаете, как сделать многопоточное программирование уже; если нет, то вам нужно узнать об этом, желательно с библиотекой Boost, а не только потоками POSIX. – chrisaycock

+0

В основном с матрицей N-размера Я хочу сказать, что у нас есть матрица 20x20x20, тогда у меня будет 8000 каталогов, которые нужно искать. Таким образом, это может быть увеличено в зависимости от требований. – Abhinav

+2

Чтобы получить хорошую производительность, независимо от того, что вы определяете для этого приложения, в конечном итоге ваше оборудование (и ОС) также будет поддерживать это. Обычно I/O является узким местом для многопоточных приложений, даже если вы разделяете работу на разные потоки, они, как правило, ожидают доступа к одному и тому же вводу-выводу, что ограничивает любой параллелизм, который вы надеетесь достичь. –

ответ

1

boost :: filesystem имеет directory_iterator и recursive_directory_iterator, первый получит все содержимое каталога, но не рекурсирует подкаталоги, последний также рекурсирует подкаталоги.

Что касается безопасности потоков, вы можете заблокировать мьютексы, а затем скопировать результаты в вектор std :: vector или two vector, один для файлов и один для каталогов, и в этом случае у вас будет хотя бы локальный снимок копия.

Для фактического «замораживания» файловая система в этой точке, чтобы остановить любой процесс, изменяющий ее, не является чем-то, что вы обычно можете сделать - вы можете попробовать установить атрибуты файла на нем только для чтения, а затем изменить его позже, но вам нужно будет иметь разрешение сделать это первым.

+0

Я не могу использовать вызовы boost :: filesystem, поскольку текущий код не поддерживал его. Поэтому мне нужно работать только с какой-то общей структурой данных C++. Также я буду работать над соглашением, которое вы предоставляете, чтобы посмотреть, как мы можем добиться хорошей производительности. :) – Abhinav

Смежные вопросы