Путаница - PullRequest
       4

Путаница

1 голос
/ 21 марта 2012

Я делаю свою домашнюю работу, что мне нужно сделать, это подсчитать каталоги и файлы данного каталога, но каждый каталог, который я обнаружил, должен быть посчитан так же с другим потоком моего процесса, это то, что я до сих пор:

void *dirCounter(void *param){
queue<pthread_t> queue;
dir_ptr dir = (dir_ptr)param;
dir->countDir = 0;
DIR* dirName = dir->name;
struct dirent *curr;
off_t dsp;
dsp= telldir(dirName);
while(dsp!= -1){
    curr = readdir(dirName);
    if(curr == NULL){
        break;
    }
    if(!strcmp(curr->d_name,".")|!strcmp(curr->d_name,"..")) {  //To avoid counting . and ..
        dsp = telldir(dirName); //Actual position asociated to the stream
        continue;   //Executes the beginning of the while
    }
    if(curr->d_type == DT_DIR){
        dir->countDir++; //counts directories in the first level
        //For each directory found, create another thread and add it to the queue:

        pthread_attr_t attr1;
        pthread_t tid1;
        pthread_attr_init(&attr1);
        dir_ptr par1 = (dir_ptr)malloc(sizeof(directorio));
        par1->name = opendir(curr->d_name);
        par1->countDir = par1->countFile = 0;
        pthread_create(&tid1,&attr1, dirCounter, par1);
        //queue.push(tid1);
    }
    if(curr->d_type == DT_REG){
        dir->countFile++; //Counts files
    }
    dsp = telldir(dirName);
}
//pthread_join(tid1, NULL);
//while(!queue.empty()){
    //pthread_join(queue.front(), NULL);
//  queue.pop();
//}
printf("Dirs: %d Files: %d\n", dir->countDir, dir->countFile);
pthread_exit(NULL); 
}

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

Модификации:

char str[256];
strcpy(str, "./");
strcat(str, curr->d_name);
//strcat(str, "\"");
puts(str);
par1->name = opendir(str);
par1->countDir = par1->countFile = 0;
pthread_create(&tid1,&attr1, dirCounter, par1);
queue.push(tid1);

Что он делает после модификации: Печатает ВСЕ каталоги, однако это вызывает ошибку сегментации, и некоторые потоки не завершают свою задачу.

Ответы [ 2 ]

2 голосов
/ 21 марта 2012

Непосредственной причиной вашей проблемы является то, что dir->name равно NULL в дополнительных созданных потоках, поскольку opendir(curr->d_name); не удается. Это связано с тем, что каталог curr->d_name не является абсолютным путем - opendir() будет искать в текущем рабочем каталоге каталог, который вы пытаетесь открыть, но этот каталог фактически находится в каталоге, который вы ' сейчас работаем над.

Я предлагаю вместо передачи значения DIR * в поток, вместо этого просто передайте путь к каталогу, и пусть поток сам сделает opendir(). Затем он должен проверить возвращаемое значение и приступить к вызову readdir(), только если opendir() вернул ненулевое значение.

Когда вы находите запись каталога, которая является каталогом, вам необходимо создать путь для передачи в новый поток путем объединения "/" и curr->d_name в путь к каталогу, который обрабатывается.

Обратите внимание, что вам не нужна переменная dsp и вызовы telldir() вообще. Если у вас есть действительный DIR *dir, вы можете зациклить его просто:

while (curr = readdir(dir)) {
    /* Do something with curr */
}
1 голос
/ 21 марта 2012

Я вижу несколько ошибок.Я не уверен, объясняет ли это ваш сбой.

Вы выделили экземпляр "Directorio" для каждого каталога и соответствующего потока.Но ты никогда не освобождаешь это.Утечка памяти.

Намерено ли печатать общее количество каталогов и файлов всей файловой системы?Или просто отдельный каталог и количество файлов для каждого каталога?Если первое, вы не добавляете результаты обратно.Я бы даже предложил, чтобы все потоки имели одинаковые целочисленные указатели для dirCount и fileCount.(И используйте блокировку для сериализации доступа или просто используйте __ sync_add_and_fetch ).Вы также можете просто использовать набор глобальных переменных для целого числа dir и количества файлов.

Если в последнем случае (каждый поток печатает собственную сумму дочерних файлов), просто передайте имя каталога (строку) в качествепараметр потока, и пусть поток использует локальные переменные из стека для счетчиков.(Поток будет вызывать opendir для переданной строки. Ему все равно потребуется освободить выделенную переданную строку.)

Вам не нужно передавать экземпляр pthread_attr_t в pthread_create.Вы можете передать NULL в качестве второго параметра и получить тот же эффект.

Вы не проверяете возвращаемое значение pthread_create.Если это не удастся (маловероятно), то значение tid1 может быть мусором.

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...