gpt4 book ai didi

c++ - 在线程应用程序(linux、pthreads)中读取文件大小时出错

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:09:10 24 4
gpt4 key购买 nike

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

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

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

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

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

    . ( 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

As you can see the highest file size under current directory it's direxp ( this program ) and the highest file size under tree it's huge

Running the binary, I got the following results:

    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.

th-prefixed strings show data processed in another thread.

I use the functions readdir (main thread) and readdir_r (spawned thread) to read directory entries.

I thought this could be the trouble, but later compiled the program calling readdir_r under all threads and the wrong results persists.

Really I don't understand why file size it's returned wrong (4096 it's default cluster size in my filesystem. So why are files processed as directories ?

Could you give me a hand ? Thanks

main function code

#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;
}

最佳答案

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

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

关于c++ - 在线程应用程序(linux、pthreads)中读取文件大小时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9026897/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com