Добавил:
north memphis Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

practic5

.c
Скачиваний:
0
Добавлен:
17.07.2026
Размер:
7 Кб
Скачать
/*
Выполнил: 
Задание №4 "Разгрузка контейнеров"
Дата выполнения 08.04.2026
Версия 0.1
Общее описание программы:
	Компиляция: gcc lab5.c -pthread
	Запуск: ./a.out
	
	Логика работа:
	
	Таймер создает поток контейнера
	Контейнер:
		встает в очередь
		сигнализирует диспетчеру
		ждет разрешения
	Диспетчер:
		берет первый контейнер
		дает разрешение
	Контейнер:
		разгружается
		освобождает ресурс
		
	PlantUML диаграмма:
	@startuml
	actor Timer1
	actor Timer2
	actor Timer3
	participant "Container" as C
	participant Dispatcher as D

	== Появление контейнера ==
	Timer1 -> C : create thread (ID=0)
	Timer2 -> C : create thread (ID=1)
	Timer3 -> C : create thread (ID=2)

	== Контейнер отправляет запрос ==
	C -> D : signal(cond_request)

	== Диспетчер ждет ==
	D -> D : wait(cond_request)

	== Диспетчер выбирает контейнер ==
	D -> D : dequeue()

	== Разрешение ==
	D -> C : signal(cond_permission)

	== Разгрузка ==
	C -> C : unloading (sleep)

	== Завершение ==
	C -> D : signal(cond_request)\n(освобождение ресурса)

	@enduml

*/

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>

#define MAX_QUEUE 100

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond_request = PTHREAD_COND_INITIALIZER;
pthread_cond_t cond_permission = PTHREAD_COND_INITIALIZER;

int queue[MAX_QUEUE];
int q_head = 0, q_tail = 0;

int current_container = -1;

int T[3] = {2, 3, 5};        // периоды появления
int unload_time[3] = {2, 3, 4};

void enqueue(int id) {
    queue[q_tail] = id;
    q_tail = (q_tail + 1) % MAX_QUEUE;
}

int dequeue() {
    int id = queue[q_head];
    q_head = (q_head + 1) % MAX_QUEUE;
    return id;
}

int is_empty() {
    return q_head == q_tail;
}

void* container_thread(void* arg) {
    int id = *(int*)arg;
    free(arg);

    pthread_t tid = pthread_self();

    printf("Container %d arrived (thread %lu)\n", id, tid);

    pthread_mutex_lock(&mutex);
    enqueue(id);

    pthread_cond_signal(&cond_request);

    while (current_container != id) {
        pthread_cond_wait(&cond_permission, &mutex);
    }

    pthread_mutex_unlock(&mutex);

    // Разгрузка
    printf(">>> Container %d unloading...\n", id);
    sleep(unload_time[id]);
    printf("<<< Container %d finished\n", id);

    pthread_mutex_lock(&mutex);
    current_container = -1;
    pthread_cond_signal(&cond_request);
    pthread_mutex_unlock(&mutex);

    return NULL;
}

void timer_handler(union sigval sv) {
    int id = sv.sival_int;

    pthread_t th;
    int* arg = malloc(sizeof(int));
    *arg = id;

    pthread_create(&th, NULL, container_thread, arg);
    pthread_detach(th);
}

void* dispatcher(void* arg) {
    while (1) {
        pthread_mutex_lock(&mutex);

        // Ждем появления контейнера
        while (is_empty() || current_container != -1) {
            pthread_cond_wait(&cond_request, &mutex);
        }

        int id = dequeue();
        current_container = id;

        printf("Dispatcher разрешает контейнеру %d\n", id);

        pthread_cond_broadcast(&cond_permission);

        pthread_mutex_unlock(&mutex);
    }

    return NULL;
}


int main() {
    pthread_t disp;
    pthread_create(&disp, NULL, dispatcher, NULL);

    timer_t timers[3];
    struct sigevent sev[3];
    struct itimerspec its[3];

    for (int i = 0; i < 3; i++) {
        sev[i].sigev_notify = SIGEV_THREAD;
        sev[i].sigev_notify_function = timer_handler;
        sev[i].sigev_notify_attributes = NULL;
        sev[i].sigev_value.sival_int = i;

        timer_create(CLOCK_REALTIME, &sev[i], &timers[i]);

        its[i].it_value.tv_sec = 1;   // первый запуск
        its[i].it_value.tv_nsec = 0;

        its[i].it_interval.tv_sec = T[i];
        its[i].it_interval.tv_nsec = 0;

        timer_settime(timers[i], 0, &its[i], NULL);
    }

    // бесконечная работа
    while (1) {
        pause();
    }

    return 0;
}


/*
@debian:~/Desktop$ gcc lab5.c -pthread
@debian:~/Desktop$ ./a.out
Container 1 arrived (thread 140119885477568)
Dispatcher разрешает контейнеру 1
>>> Container 1 unloading...
Container 0 arrived (thread 140120102872768)
Container 2 arrived (thread 140119877084864)
Container 0 arrived (thread 140120119658176)
Container 1 arrived (thread 140120128050880)
>>> Container 1 unloading...
<<< Container 1 finished
Dispatcher разрешает контейнеру 0
>>> Container 0 unloading...
>>> Container 0 unloading...
Container 0 arrived (thread 140120111265472)
>>> Container 0 unloading...
Container 2 arrived (thread 140119868692160)
<<< Container 0 finished
<<< Container 0 finished
Dispatcher разрешает контейнеру 2
>>> Container 2 unloading...
>>> Container 2 unloading...
Container 0 arrived (thread 140119885477568)
<<< Container 1 finished
Container 1 arrived (thread 140120102872768)
Dispatcher разрешает контейнеру 0
>>> Container 0 unloading...
<<< Container 0 finished
Dispatcher разрешает контейнеру 1
>>> Container 1 unloading...
<<< Container 0 finished
Dispatcher разрешает контейнеру 0
Container 0 arrived (thread 140119885477568)
>>> Container 0 unloading...
Container 1 arrived (thread 140120128050880)
<<< Container 2 finished
<<< Container 2 finished
Dispatcher разрешает контейнеру 2
<<< Container 1 finished
Dispatcher разрешает контейнеру 0
Container 0 arrived (thread 140119868692160)
>>> Container 0 unloading...
Container 2 arrived (thread 140120111265472)
<<< Container 0 finished
Dispatcher разрешает контейнеру 1
>>> Container 1 unloading...
<<< Container 0 finished
Dispatcher разрешает контейнеру 0
Container 1 arrived (thread 140119877084864)
Container 0 arrived (thread 140120119658176)
>>> Container 0 unloading...
<<< Container 1 finished
Dispatcher разрешает контейнеру 1
>>> Container 1 unloading...
Container 0 arrived (thread 140119885477568)
<<< Container 0 finished
Dispatcher разрешает контейнеру 0
>>> Container 0 unloading...
^C
@debian:~/Desktop$
*/
Соседние файлы в предмете Системы реального времени