1

std::filesystem (std::filesystem::recursive_directory_iterator を使用した再帰検索) を使用して、システム上の名前でファイルを検索するプログラムを作成しました。Linux でルート ("/") ディレクトリから開始した場合、メイン スレッドを 1 つだけ使用し、実行時間は約 1 秒で、正常に動作します。問題: 複数のスレッドを使用してこのプログラムを実行しようとすると、Aborted (コア ダンプ) が発生し、ファイル システム エラー: recursive directory iterator cannot open directory: Not a directory が発生します。関数を実行したい

bool SearchFile::find_file_in_directory(const std::string file_name, fs::path path) 

同時に8つのスレッドで、ただし異なるパラメーターを使用します(パスパラメーターは別のものになります)。この方法でマルチスレッドを実装しようとしました。システム上の既存のすべてのファイルの数を計算し、この数をスレッドの数で割り、各スレッドエントリディレクトリを指定して検索を開始します。また、SearchFile (sf) というファイルを操作するための独自のクラスもあります。以下にリストされているコード:

最初に1つのスレッドの方法(必要に応じて機能します):

bool SearchFile::find_file_from_directory(const std::string file_name,
                                          fs::path path) {
  if (fs::is_directory(path))
    for (auto &p : fs::recursive_directory_iterator(
             path, fs::directory_options::skip_permission_denied)) {
      path = p;
      if (path.filename() == file_name) {
        curr_path = path;
        return true;
      } else {
        // uncomment this line to see how the function search file
        // std::cout<<path<<"\n";
        continue;
      }
    }
  else
    std::cout << "Entered path is not a directory\n";

  return false;

  std::cout << "File doesn`t exist\n";
  return false;
}

私が使用するSearchFileのメソッド:

bool SearchFile::find_file_in_directory(const std::string file_name,
                                        fs::path path) {
  if (fs::is_directory(path))
    path /= file_name;
  if (fs::exists(path)) {
    return true;
  } else
    std::cout << "Entered path is not a directory\n";
  return false;

  std::cout << "File doesn`t exist\n";
  return false;
}

u_int SearchFile::get_num_of_files_recursively(const fs::path path) {
  u_int num = 0;
  if (fs::is_directory(path)) {
    for (fs::recursive_directory_iterator it(
             path, fs::directory_options::skip_permission_denied);
         it != fs::recursive_directory_iterator(); ++it) {
      num++;
    }
  } else {
    std::cout << "Entered path is not a directory\n";
    return 0;
  }
  return num;
}

main.cpp

#include <iostream>
#include <string>
#include <thread>
//#include "library/searchfile.h"
#include <condition_variable>
#include <fstream>
#include <vector>
//#pragma once
#include <filesystem>

SearchFile sf;
std::condition_variable cv;
std::vector<fs::path> arr;

void do_division(const fs::path path, const u_int times) {
  u_int files_num = sf.get_num_of_files_recursively(path),
        part = files_num / times;
  u_int i = 0;
  arr.push_back(path);
  for (fs::recursive_directory_iterator it(path, fs::directory_options::skip_permission_denied);
       it != fs::recursive_directory_iterator(); ++it) {
    if (i == part) {
      arr.push_back(it->path());
      part += part;
    }
    i++;
  }
}

void do_job(const fs::path path, const std::string name) noexcept {
  for (auto &p : fs::recursive_directory_iterator(path, fs::directory_options::skip_permission_denied)) {
    std::cout << std::this_thread::get_id() << " - " << p.path() << "\n";

    if (sf.find_file_in_directory(name, p.path())) {
      cv.notify_all();
      std::fstream f;
      std::string path = p.path().string();
      f.open(path);
      f << path;
      f.close();
      return;
    }
  }
}

int main() {
  std::string filename = "MyFile.txt";
  std::string path = "/";

  do_division("/", 8);

  while (1) {
    std::thread t1(do_job, arr[0], filename);
    t1.detach();

    std::thread t2(do_job, arr[1], filename);
    t2.detach();

    std::thread t3(do_job, arr[2], filename);
    t3.detach();

    std::thread t4(do_job, arr[3], filename);
    t4.detach();

    std::thread t5(do_job, arr[4], filename);
    t5.detach();

    std::thread t6(do_job, arr[5], filename);
    t6.detach();

    std::thread t7(do_job, arr[6], filename);
    t7.detach();

    std::thread t8(do_job, arr[7], filename);
    t8.detach();
  }
  return 0;
}

私の問題を解決する良い方法ではないかもしれませんが、私は初心者です。

4

0 に答える 0