Модераторы: xvr
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Распараллеливание процессов Unix 
:(
    Опции темы
Alexis777
Дата 14.5.2018, 19:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 1
Регистрация: 14.5.2018

Репутация: нет
Всего: нет



Добрый день помогите реализовать программу инвертирования содержимого файлов из нескольких подкаталогов (каждый процесс работает со своим файлом) двумя параллельными алгоритмами:

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;

    }

}


Всем заранее спасибо за помощь)
PM MAIL   Вверх
xvr
Дата 15.5.2018, 12:38 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 20
Всего: 223



У вас напрашивается такая структура программы:
  • При старте программа создаёт канал обмена информацией, по которому она будет передавать имена файлов которые надо инвертировать
  • Затем она стартует (через fork) несколько обработчиков, которые и будут инвертировать файлы
  • Затем она сканирует директории и отправляет именя файлов в канал (читать их оттуда будут обработчики)
  • По окончании она отправляет в канал несколько специальных сообщений EOW (по числу обработчиков)
  • Ждёт завершания всех обработчиков и завершается сама
Обработчик делает следующее:
  • Читает из канала (в блокирующем режиме) имя файла и инвертирует его
  • Если вместо имени файла пришло EOW - завершается
Канал обмена может быть строен 2 путями (по вашему заданию):
  • Очередь сообщений, в которую пушат сообщения с именем файла (или сообщение например нулевой длинны для обозначения EOW). Куда тут ещё пристегнуть сигналы - непонятно.
  • Кусок разделяемой памяти, в которой лежит очередь с именами файлов в виде массива с указателями чтения и записи (классический кольцевой буфер). Что бы параллельно работающие процессы не порубали его в капусту доступ ограничивается семафором, работающим в режиме мьютекса - даёт доступ только 1 процессу за раз.
Собственно всё


Это сообщение отредактировал(а) xvr - 15.5.2018, 12:39
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Программирование под Unix/Linux"
xvr
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • Не забывайте пользоваться кнопкой "Код".
  • Вопросы мобильной разработки тут
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к разделу форума. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, xvr.

 
 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Программирование под Unix/Linux | Следующая тема »


 




[ Время генерации скрипта: 0.1189 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.