Показать сообщение отдельно
Старый 14.05.2018, 20:11   #1 (permalink)
Alexis777
Новичок
 
Регистрация: 14.05.2018
Сообщений: 1
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Репутация: 10
По умолчанию Распараллеливание процессов: реализовать инвертирование содержимого файлов Unix

Добрый день помогите реализовать программу инвертирования содержимого файлов из нескольких подкаталогов (каждый процесс работает со своим файлом) двумя параллельными алгоритмами:
1) с использованием сигналов и очереди сообщений;
2) с использованием семафоров и разделяемой памяти.
Читал теорию, но как делать не понял. Буду рад любой помощи)
Теорию прикрепил, если кто захочет помочь)
Саму программу сделал:
Код:
#include <iostream>
#include <fstream>
#include <algorithm>
#include <iterator>
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;

void reverseFile(fs::path pfile, fs::path const& pdir)
{
    std::fstream ifs(pfile, std::ios::in), ofs(pdir / pfile.filename(), std::ios::out);
    if (ifs.is_open() && ofs.is_open())
    {
        std::string str{ std::istreambuf_iterator<char>{ifs.rdbuf()}, {} };
        std::reverse_copy(str.begin(), str.end(), std::ostreambuf_iterator<char>(ofs));
    }
    else
    {
        std::cerr << "Unable to open file(s): " << pfile << "  " << pdir / pfile.filename() << "\n\n";
    }
    ifs.close();
    ofs.close();
}

// создаём путь папки в каталоге с инвертированными файлами
fs::path newPath(fs::path const& oldPth, fs::path const& pd1, fs::path const& pd2)
{
    fs::path ret = pd2;
    auto pr = std::mismatch(oldPth.begin(), oldPth.end(), pd1.begin(), pd1.end());

    for (auto ib(pr.first), ie(oldPth.end()); ib != ie; ++ib)
    {
        ret /= *ib;
    }

    return ret;
}

int main()
{
    try
    {
        fs::path pd1("C:\\dir1"); // каталог с исходными файлами
        fs::path pd2("C:\\dir2"); // каталог с инвертированными файлами
        if (!fs::exists(pd2))
        {
            fs::create_directories(pd2); // может кинуть исключение
        }
        for (fs::recursive_directory_iterator ib(pd1), ie; ib != ie; ++ib) // перебираем все файлы в dir 1
        {
            if (fs::is_regular_file(ib->path())) // инвертируем каждый файл
            {
                reverseFile(ib->path(), newPath(ib->path(), pd1, pd2));
            }
            else if (fs::is_directory(ib->path())) // создаём папку в каталоге с инвертированными файлами
            {
                fs::create_directory(newPath(ib->path(), pd1, pd2));
            }
        }
    }
    catch (std::exception const& exc)
    {
        std::cerr << "Exception: " << exc.what() << std::endl;
    }
}
Также есть с потоками реализация делал:
Код:
#include <iostream>
#include <fstream>
#include <list>
#include <pthread.h>
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;

pthread_mutex_t mtxCerr;

struct var
{
    var(fs::path const& pf1, fs::path const& pf2) : pfile1(pf1), pfile2(pf2){};
    fs::path pfile1;
    fs::path pfile2;
};

void* reverseFile(void* arg)
{
    fs::path pfile1(reinterpret_cast<var*>(arg)->pfile1);
    fs::path pfile2(reinterpret_cast<var*>(arg)->pfile2);
    std::fstream ifs(pfile1, std::ios::in | std::ios::binary), ofs(pfile2, std::ios::out | std::ios::binary);
    if (ifs.is_open() && ofs.is_open())
    {
        ifs.seekg(0, ifs.end);
        if (ifs.tellg() >= std::streampos(1))
        {
            for (ifs.seekg(-1, ifs.cur); ; ifs.seekg(-2, ifs.cur))
            {
                char c = ifs.get();
                //std::cout << int(c) << "  ";
                ofs.put(c);
                if (ifs.tellg() == std::streampos(1))
                {
                    break;
                }
            }
        }
    }
    else
    {
        pthread_mutex_lock(&mtxCerr);
        std::cerr << "Unable to open file(s): " << pfile1 << "  " << pfile2 << "\n\n";
        pthread_mutex_unlock(&mtxCerr);
    }
    ifs.close();
    ofs.close();

    pthread_exit(0);
}

fs::path newPath(fs::path const& oldPth, fs::path const& pd1, fs::path const& pd2)
{
    fs::path ret = pd2;
    auto pr = std::mismatch(oldPth.begin(), oldPth.end(), pd1.begin());

    for (auto ib(pr.first), ie(oldPth.end()); ib != ie; ++ib)
    {
        ret /= *ib;
    }

    return ret;
}

int main()
{
    try
    {
        fs::path pd1("/home/user/student/dir1"); // каталог с исходными файлами
        fs::path pd2("/home/user/student/dir2/ddd"); // каталог с инвертированными файлами

        pthread_mutex_init(&mtxCerr, nullptr);

        if (!fs::exists(pd2))
        {
            fs::create_directories(pd2); // может кинуть исключение
        }

        std::list<pthread_t> lt;
        std::list<var> la;
        for (fs::recursive_directory_iterator ib(pd1), ie; ib != ie; ++ib) // перебираем все файлы в dir 1
        {
            if (fs::is_regular_file(ib->path())) // инвертируем каждый файл
            {
                lt.emplace_back();
                la.emplace_back(ib->path(), newPath(ib->path(), pd1, pd2));
                pthread_create(&lt.back(), nullptr, reverseFile, &la.back());
            }
            else if(fs::is_directory(ib->path()))
            {
                fs::create_directory(newPath(ib->path(), pd1, pd2));
            }
        }
        for(auto& thr : lt)
        {
            pthread_join(thr, nullptr);
        }
        pthread_mutex_destroy(&mtxCerr);
    }
    catch (std::exception const& exc)
    {
        std::cerr << "Exception: " << exc.what() << std::endl;
    }
}
Всем заранее спасибо за помощь)
Вложения
Тип файла: doc (fork).doc (305.0 Кб, 112 просмотров)
Alexis777 вне форума   Ответить с цитированием
Ads

Яндекс

Member
 
Регистрация: 31.10.2006
Сообщений: 40200
Записей в дневнике: 0
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Репутация: 55070