Добавил:
Вуз:
Предмет:
Файл:
practic5
.c/*
Выполнил:
Задание №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$
*/
Соседние файлы в предмете Системы реального времени
