LINUX.ORG.RU

Разработка многопоточного приложения средствами POSIX в ОС Linux

 , ,


2

2

Ребят, учусь в УУМЗ, и препод решил всех удивить своими познаниями в программировании. Но с нами ими не поделился, только дал задание. Помогоите пожалуйста написать код, удовлетворяющий заданию. Вершины графа являются точками запуска/завершения потоков, дугами обозначены сами потоки, длину дуги следует интерпретировать как ориентировочное время выполнения потока. Реализовать последовательно-параллельный запуск потоков в ОС Linux с использованием средств POSIX для запуска и синхронизации потоков. Запрещается использовать какие-либо библиотеки и модули, решающие задачу кроссплатформенной разработки многопоточных приложений (std::thread, Qt Thread, Boost Thread и т.п.). Самостоятельно выделить на графе две группы с выполняющимися параллельно потоками. Первая группа не синхронизирована, параллельное выполнение входящих в группу потоков происходит за счет использования искусственной задержки. Величина задержки должна быть как можно меньше. При выполнении операций ввода-вывода перед входом в критическую секцию потоки должны захватывать мьютекс. Вторая группа синхронизирована семафорами: входящий в групу поток передает управление другому потоку после каждой итерации. Последовательное выполнение потоков должно обеспечиваться за счет использования семафоров. Все потоки должны запускаться одновременно из функции k1_init(), без задержек, один за другим. Использовать функцию pthread_join() разрешается только в функции k1_init() для ожидания завершения работы всех запущенных потоков. Вот этот граф. http://d.radikal.ru/d38/1903/45/c004a55e6571.png



Последнее исправление: ishka (всего исправлений: 1)

Ответ на: комментарий от Harald

а скока это в абсолютных цифрах

Оставлю это в тайне.

обладателям ВО может светить и в десять раз больше (ну тем, кто не просиживал штаны, а действительно учился)

Точно так же как и тем у кого нет во.

rumgot ★★★★★
()
Ответ на: комментарий от gag

А что, код pthread_create реализован на pthread? Как связано использование библиотеки с реализацией это библиотеки?

i-rinat ★★★★★
()
Ответ на: комментарий от rumgot

Чего мелочиться, берём список Forbes, или вот этот

https://en.wikipedia.org/wiki/The_World's_Billionaires#2019

Кроме Билла Гейтса и Цукерберга, большинство миллиардеров таки имеет диплом, и не один (но и они всё равно получили почётные степени от своих шараг, в которых они не доучились). Вывод - с ВО шансов стать богатым больше, чем без него

Harald ★★★★★
()
Последнее исправление: Harald (всего исправлений: 1)
Ответ на: комментарий от Harald

Бесспорно. Но это не определяющий фактор.

rumgot ★★★★★
()
Ответ на: комментарий от Harald

большинство миллиардеров таки имеет диплом
Вывод - с ВО шансов стать богатым больше, чем без него

большинство миллиардеров
стать богатым

Стыдно, стыдно, молодой человек, делать такие ошибки.

LamerOk ★★★★★
()
Ответ на: комментарий от Harald

«На мое коровье ухо повесили бирку больше, чем на соседскую».:-)

rumgot ★★★★★
()
Ответ на: комментарий от rumgot

Канеш, так большинство работает: ничего не изучают, а когда плнадобится, со стековерфлоу копируют

annulen ★★★★★
()
Ответ на: комментарий от slovazap

Подсказка: код надо не только писать, но и читать. Иногда даже код реализации этих удобных оберток.

annulen ★★★★★
()
Последнее исправление: annulen (всего исправлений: 1)
Ответ на: комментарий от gag

Бида-бида, все кросс-платформенные обертки и даже целые языки прграммирования на линуксе используют внутри pthreads. Мы все умрем :/

annulen ★★★★★
()
Ответ на: комментарий от i-rinat

Я больше о том, что несмотря на стремление скрыть сложность в простом на вид интерфейсе, тем не менее простой пользователь может таки на неё наткнуться. И почему мне запомнился тот пример, что споткнуться можно даже о самую базовую функцию интерфейса.

gag ★★★★★
()
Ответ на: комментарий от annulen

И я использую (кроме cancel-функциональности), но могут быть вот такие сюрпризы на ровном месте. А что там ещё в неровных местах скрыто...

gag ★★★★★
()

Печатает таймлайн на stdout для визуального контроля. Про деление на две группы не понял.

#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <unistd.h>

// each semaphore is posted by task on exit
static sem_t sem_a;
static sem_t sem_b;
static sem_t sem_c;
static sem_t sem_d;
static sem_t sem_e;
static sem_t sem_f;
static sem_t sem_h;
static sem_t sem_i;
static sem_t sem_k;
static sem_t sem_m;
static sem_t sem_r;

void init_sems()
{
    sem_init(&sem_a, 0, 0);
    sem_init(&sem_b, 0, 0);
    sem_init(&sem_c, 0, 0);
    sem_init(&sem_d, 0, 0);
    sem_init(&sem_e, 0, 0);
    sem_init(&sem_f, 0, 0);
    sem_init(&sem_h, 0, 0);
    sem_init(&sem_i, 0, 0);
    sem_init(&sem_k, 0, 0);
    sem_init(&sem_m, 0, 0);
    sem_init(&sem_r, 0, 0);
}

// semaphore wait groups
static sem_t* const wait_a[]   = {&sem_a, nullptr};
static sem_t* const wait_b[]   = {&sem_b, nullptr};
static sem_t* const wait_cd[]  = {&sem_c, &sem_d, nullptr};
static sem_t* const wait_eir[] = {&sem_e, &sem_i, &sem_r, nullptr};
static sem_t* const wait_hf[]  = {&sem_h, &sem_f, nullptr};
static sem_t* const wait_km[]  = {&sem_k, &sem_m, nullptr};

struct task
{
    size_t index;
    char name;
    int duration_ms;
    sem_t* post_sem; // semaphore posted on task stop
    sem_t* const* wait_sems; // semaphore group waited on task start
};

static const task task[] =
{
    { 0, 'a', 1000, &sem_a,  nullptr},
    { 1, 'b', 1000, &sem_b,  wait_a},
    { 2, 'c', 1300, &sem_c,  wait_a},
    { 3, 'd', 1000, &sem_d,  wait_b},
    { 4, 'e', 2200, &sem_e,  wait_b},
    { 5, 'f', 2500, &sem_f,  wait_a},
    { 6, 'g', 6000, nullptr, wait_b},
    { 7, 'h',  900, &sem_h,  wait_cd},
    { 8, 'i', 1200, &sem_i,  wait_hf},
    { 9, 'k', 1000, &sem_k,  wait_eir},
    {10, 'm', 1300, &sem_m,  wait_hf},
    {11, 'n', 2400, nullptr, wait_hf},
    {12, 'p', 1000, nullptr, wait_km},
    {13, 'r', 1500, &sem_r,  wait_cd},
};

constexpr auto count = sizeof(task)/sizeof(task[0]);

// status string: active tasks are letters, inactive tasks are hyphens.
// status string should be accessed after holding mutex only.
static char status[count + 1];
static pthread_mutex_t mutex;

void init_status()
{
    for (size_t i = 0; i != count; ++i)
    {
        status[i] = '-';
    }
    status[count] = '\n';
}

void set_status(size_t index, char c)
{
    pthread_mutex_lock(&mutex);
    status[index] = c;
    pthread_mutex_unlock(&mutex);
}

// print status and return false if all tasks are inactive.
bool print_status()
{
    pthread_mutex_lock(&mutex);
    write(STDOUT_FILENO, status, sizeof(status));
    bool finished = true;
    for (size_t i = 0; i != count; ++i)
    {
        if (status[i] != '-')
        {
            finished = false;
            break;
        }
    }
    pthread_mutex_unlock(&mutex);
    return !finished;
}

// all tasks are running same thread function.
// task config is passed as thread function argument.
void* thread_func(void* arg)
{
    const auto config = reinterpret_cast<const struct task*>(arg);
    if (config->wait_sems)
    {
        for (auto semp = config->wait_sems; *semp; ++semp)
        {
            sem_wait(*semp);
            sem_post(*semp);
        }
    }
    set_status(config->index, config->name);
    usleep(config->duration_ms*1000);
    set_status(config->index, '-');
    if (config->post_sem)
    {
        sem_post(config->post_sem);
    }
    return nullptr;
}

void k1_init()
{
    // initialize stuff and start all tasks
    init_status();
    init_sems();
    pthread_mutex_init(&mutex, nullptr);
    pthread_t thr[count];
    for (size_t i = 0; i != count; ++i)
    {
        pthread_create(&thr[i], nullptr, thread_func,
                       const_cast<struct task*>(&task[i]));
    }

    // main thread prints timeline
    while (print_status())
    {
        usleep(100*1000);
    }

    // join all tasks
    for (size_t i = 0; i != count; ++i)
    {
        pthread_join(thr[i], nullptr);
    }
}

int main(void)
{
    k1_init();
    return 0;
}
iliyap ★★★★★
()
Ответ на: комментарий от Iron_Bug

А я бы еще заставил написать собственную реализацию, для лучшего понимания многопоточности.

cvv ★★★★★
()
Ответ на: комментарий от gag

Ты каким-то странным образом формулируешь простое: «в программах бывают ошибки». И на основе наличия ошибок в реализации делаешь вывод о том, что API плохое?

Что странно, про недостатки API предметно никто не пишет. А ведь в pthread есть проблемы.

i-rinat ★★★★★
()
Ответ на: комментарий от deadplace

Если мозги есть, это не нужно, если их нет, это не поможет.

WitcherGeralt ★★
()
Ответ на: комментарий от rumgot

У меня тоже нет высшего, но я вижу, что у тебя пригорело. Это, конечно, хорошо, что ты можешь решать задачи с помощью высокоуровневых инструментов, но это не означает, что ты не должен знать азы. Нужно отдавать себе отчёт о существовании у тебя пробелов в некоторых фундаментальных вещах, а не заявлять: «нинужно, у меня есть libзбс, которая всё сделает за меня».

И да, васяны и макаки меня бесят не меньше, чем они ьесят @Iron_Bug. Себя к васянам не отношу по одной простой причине: я всегда пытаюсь разобраться в предмете и никогда не пользуюсь Stack Overflow driven подходом.

WitcherGeralt ★★
()
Ответ на: комментарий от rumgot

Лень заставляет думать вместо перебора решений ака «методика бесконечных обезьян», а также помогает в автоматизации процессов.

WitcherGeralt ★★
()
Ответ на: комментарий от rumgot

Безусловно. Проблема не в ВО, а в обезьянах. В чукчах, которые «не читатель».

WitcherGeralt ★★
()
Ответ на: комментарий от Harald

Прикол в том, что это не самое главное. Посмотри на первую десятку (всю, включая тобой названных) и посмотри на Брэнсона. На их фоне он нищий, но кто круче, по-моему, даже не вопрос.

WitcherGeralt ★★
()
Ответ на: комментарий от rumgot

ходят целый день к этой кофемашине и электронной сигаретой дым пускают. А я вот кем только не работал до ИТ: и подсобником на стройке и электромонтером и грузчиком (программированием и компами с детства занимался в качестве увлечения). И поэтому я знаю цену денег

Отличный пост, показывающий суть IT элиты. Только могут хлебать смузи и гордится своими долларовыми З/п

deadplace
()
Ответ на: комментарий от fsb4000

pthread никто не относит к кроссплатформенным

Либа работающая на Windows...

Тысяча извинений. Как давно (и какая? кто автор?) библиотека pthread_ появилась под Windows?

Более того. Существуют ли какие-либо механизмы заставить корпорацию Microsoft добавить эти функции к штатным _beginthread*?

anonymous
()
Ответ на: комментарий от anonymous

Development began in 1998

https://sourceforge.net/projects/pthreads4w/

их было много разных версий. но году в 2003-м они уже вполне себе неплохо работали под 32 бита. потом появились 64-битные версии. потом я свалила с маздая и дальше не знаю, что там происходило :)

Iron_Bug ★★★★★
()
Ответ на: Оригинально! Браво! от Moisha_Liberman

по ссылке очередное скрипторылое «чудовище» не осилило вкурить как и что

ну ты же не берёшься писать glibc. вот и пишут кто попало.

anonymous
()
Ответ на: комментарий от WitcherGeralt

Взять готовое решение со stackoverflow - это и есть лень. А перечитать десяток тем с подобнымм вопросами, потом поискать инфу о данной теме в книгах/ документации и в итоге выбрать оптимальное решение - вот тут нужно в итоге затратить больше сил и времени.

rumgot ★★★★★
()
#include <pthread.h>
#include <stdio.h>
#include <string.h>

void *thread_func(void *arg)
{
    printf("Thread '%c' func\n", (int) arg);
    return 0;
}
unsigned char *cj[] = { "a", "a", "bcf", "b", "deg", "cd",
    "hr", "fh", "imn", "eri", "k", "mk", "p", "gnp"
};
int main(void)
{
    pthread_t ta[256];
    int i, ce;
    unsigned char *p;

    for (i = 0; i < sizeof(cj) / sizeof(cj[0]); i++) {
        if ((i & 1) == 0) {
            for (p = cj[i]; *p != '\0'; p++)
                if ((ce =
                     pthread_create(&(ta[*p]), NULL, thread_func,
	    (void *) ((int) (*p)))) != 0) {
                    fprintf(stderr, "%s\n", strerror(ce));
                    return 1;
                } else
                    printf("Thread '%c' created\n", *p);
        } else {
            for (p = cj[i]; *p != '\0'; p++) {
                pthread_join(ta[*p], NULL);
                printf("Thread '%c' join\n", *p);
            }
        }
    }
    return 0;
}

Зацените

anonymous
()
Ответ на: комментарий от rumgot

Эта не та лень, которая на диване валяться. И хватит тут кичиться тем, что вышку не получил, это очень сомнительное достижение. Отсутствие образования и так в ваших постах и образе мыслей читается.

anonymous
()
Ответ на: комментарий от anonymous

Читается потому что написал про это. Иначе бы у тебя и повода не было бы.

rumgot ★★★★★
()
Ответ на: комментарий от deadplace

С радио ты уже облажался в этом треде, мог бы другой пример взять. Я может и очень поверхностно, но кое чего знаю, всё же физику учил, а в детстве активно занимался в конструкторском кружке. Если что, разберусь.

И ты передёргиваешь, одно дело пользоваться, другое дело что-то разрабатывать. В пером случае можно не приходить в сознание, а во втором нужно иметь полную картину.

WitcherGeralt ★★
()
Ответ на: комментарий от hateyoufeel

Под который больше вакансий и выше потолок зарплат чем за C.

что больше, не спорю, но про какой потолок за С ты имеешь в виду?

Вот Линус Торвальдс пишет на С, у него миллион баксов в год. Этот потолок?

Harald ★★★★★
()
Ответ на: комментарий от anonymous

Известных реализаций pthread под винду как минимум две, одна вроде даже из коробки вместе с mingw идёт. Ещё вопросы?

Harald ★★★★★
()

Фсмысле?

Зачем писать ещё одну glibc? Её не хватает? И, вдобавок, как минимум ещё двух альтернатив в виде uClibc (uclibc-ng) и musl?

Может, всё проще? Просто писать научитесь?

Moisha_Liberman ★★
()
Ответ на: комментарий от Harald

Не.

Это основатель Целка, пардон, Virgin Group. Включает в себя порядка 400 компаний разного профиля. Типа, один из самых богатых среди подданых Её Величества.

Moisha_Liberman ★★
()
Ответ на: комментарий от Harald

Лишняя библиотека - это лишняя зависимость

Не раскрыта необходимость pthread для обертывания clone() и CreateThread() на какой-то либо из целевых платформ :) Что за полумеры — пущай ТС свою обертку городит СБИШ — а то какое-то непонятное предпочтение одной обертки другим «в кросплатформенной» задаче :)

slackwarrior ★★★★★
()
Последнее исправление: slackwarrior (всего исправлений: 1)
Ответ на: комментарий от Harald

Или нет — особенно это касается CreateThread, который pthread нат той платформе оборачивает :) А то некоторые из «приглашенных экспертов» свалили с мастдая и не помнят как там щас (или упарываются бустом для всего). А иногда проще таки брать std threads и не тянуть лишних зависимостей (включая буст, если бустизмы в проекте скорее не желательны, ну и пофиг что на некоторых платформах это будет все одно -lpthread где-то в системе сборки :)) Ну и да: если речь пошла о лишних обертках, то использование pthread — чит голимый, и понт автоматом не засчитывается :)

slackwarrior ★★★★★
()
Последнее исправление: slackwarrior (всего исправлений: 1)
Ответ на: комментарий от WitcherGeralt

«Лень - двигатель прогресса» - это лукавство. Все великие ученые, которые изобрели что-то делающее жизнь проще, после этого изобретения работали до самой смерти, чтобы изобрести что-то еще.

rumgot ★★★★★
()
Ответ на: комментарий от slackwarrior

ну на маздае всё печально, зависимости приходится тащить (и они ещё могут от pthread зависеть), так что увы

Harald ★★★★★
()
Ответ на: комментарий от Harald

На начальном этапе, пока не выработается неприязнь к велостроению, эти «задания» в голове сами должны рождаться сотнями. Плюс сейчас дофига онлайн-курсов и тестов.

Ну и никто тебе не даст гарантию, что давать задания и тестировать тебя будут компетентные люди. Разведав обстановку, я так документы забрал. Хотя, конечно, я изначально относился к этому скептически и просто хотел облегчить себе жизнь, получив сертификат «не верлюда».

Сейчас как раз знакомая попросила помочь с дипломной работой. Задача предельно неадекватная, единственное решение которой в заданных условиях — куча хардкора и имитация выполнения некого анализа (проверка сайтов местных властей на соответствие требованиям законодательства). Причём, судя по ответам её руководителя на список вопросов, который я набросал, именно такое решение от неё и ждут. Ладно хоть приложение кроссплатформенное хотят. Уже набросал ей материалов для чтения на пару недель, пересажу на линукс, набросаю рабочий шаблон проекта и отправлю в свободное плавание.

WitcherGeralt ★★
()
Последнее исправление: WitcherGeralt (всего исправлений: 1)
Ответ на: комментарий от Harald

зависимости приходится тащить (и они ещё могут от pthread зависеть)

Или нет :) От pthread код начинает зависеть только на онтопике, например :)

slackwarrior ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.