【问题标题】:Error reading file size in threaded application (linux,pthreads)在线程应用程序(linux,pthreads)中读取文件大小时出错
【发布时间】:2012-01-26 23:15:53
【问题描述】:

我正在尝试从带有线程的 linux 文件夹中读取所有文件和目录 获取当前目录和当前目录树下的最大文件大小和名称。

主线程扫描基本目录查找文件,当找到一个目录时,会生成一个新线程继续扫描。

此时,线程加入,直到最后创建的线程结束。 (我知道这不是最好的方法,但这只是一种练习。)

问题是程序返回错误的结果,我不知道为什么。

我有以下文件树来测试应用程序:

. (codelite项目/工作区下的Debug文件夹) ├── [4096] 目录1 │ └── [ 9] arch-dir1.txt ├── [4096] 目录2 │ ├── [27]arch-dir2.txt │ └── [ 29083] 巨大 ├── [29053] direxp ├── [27048] direxp.o └── [ 68] direxp.o.d

您可以看到当前目录下的最大文件大小是 direxp(这个程序),而树下的最大文件大小是巨大的

运行二进制文件,我得到以下结果:

目录:。 目录:.. 拱门:direxp.o.d 最大目录和树设置为:direxp.o.d 大小:68 拱门:direxp.o 最大文件目录设置为:direxp.o 大小:27048 拱门:.d 拱门:direxp 最大文件目录设置为:direxp 大小:29053 目录:目录1 第目录:。 目录:.. th 拱门:arch-dir1.txt thsize:4096 最大树文件设置为:arch-dir1.txt thsize:4096 目录:目录2 第目录:。 目录:.. th 拱门:arch-dir2.txt thsize:4096 th 拱门:巨大 thsize:4096 最高当前目录文件: direxp tam:29053 字节。 最高树文件: arch-dir1.txt tam:4096 字节。

带前缀的字符串显示在另一个线程中处理的数据。

我使用函数 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;
}

【问题讨论】:

    标签: c++ linux multithreading pthreads


    【解决方案1】:

    我建议您检查您正在进行的 stat() 调用的返回值。

    在工作线程中,您正在打印看起来不错的 thentry.d_name,但是,如果没有与您的工作目录相关的路径信息,我相信对 stat(thentry.d_name,&amp;thstat); 的调用会失败。

    【讨论】:

      【解决方案2】:

      我不建议创建单独的线程来扫描每个目录。这个程序是 I/O-bound,所以它不会通过使用多个线程运行得更快。如果有的话,它会运行得更慢,因为几个线程同时从不同的地方读取,迫使磁盘到处寻找。

      您最好使用单个线程并对目录树进行简单的深度优先或广度优先遍历。

      【讨论】:

        猜你喜欢
        • 2010-11-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-28
        • 2012-05-27
        • 2017-11-27
        • 1970-01-01
        相关资源
        最近更新 更多