Przeglądaj źródła

Merge branch 'master' of u23-27gurkin/EASvZI into master

ypv 4 miesięcy temu
rodzic
commit
d91e4f6c0a

BIN
Лекции/2.5.1200_Управление_режимом_потоков/Gurkin.jpg


+ 44 - 0
Лекции/2.5.1200_Управление_режимом_потоков/Gurkin.md

@@ -0,0 +1,44 @@
+# Управление режимом потоков
+
+![](Gurkin.jpg)
+
+
+Поток выполнения (thread) представляет собой наименьшую единицу обработки, которой операционная система выделяет процессорное время. В отличие от процессов, потоки одного приложения разделяют адресное пространство и ресурсы, что ускоряет обмен данными, но требует осторожной синхронизации. Ключевая задача планировщика – управление режимами потоков: пользовательским (user mode) и режимом ядра (kernel mode). Переход между ними (переключение контекста) занимает сотни тактов процессора, поэтому частая смена режимов снижает общую производительность системы.
+
+### Основные алгоритмы планирования потоков
+
+Современные ОС используют различные дисциплины диспетчеризации, каждая из которых подходит для определённого класса задач.
+
+1. **FCFS (First Come, First Served)** – простейший невытесняющий алгоритм. Потоки выполняются в порядке поступления. Недостаток: «эффект конвоя», когда короткий поток вынужден ждать завершения длинного. Применяется в пакетной обработке.
+
+2. **Round Robin (RR)** – циклическое планирование с квантом времени (обычно 10–100 мс). Каждый поток получает фиксированный отрезок CPU. Обеспечивает низкую задержку отклика для интерактивных приложений. Недостаток: частые переключения контекста.
+
+3. **Приоритетное планирование** – каждому потоку назначается числовой приоритет (чем меньше число, тем выше приоритет). Планировщик всегда выбирает готовый поток с наивысшим приоритетом. Возможно вытеснение (preemptive) и невытесняющее (non-preemptive). Основная проблема – «голодание» низкоприоритетных потоков. Решение – старение приоритетов: со временем приоритет ожидающего потока искусственно повышается.
+
+4. **Многоуровневые очереди с обратной связью** – потоки разделены на классы (фоновые, интерактивные, реального времени). Каждая очередь использует свой алгоритм (например, RR для интерактивных, FCFS для фоновых). Поток может переходить между очередями в зависимости от поведения (использовал весь квант – понижается в очередь).
+
+### Управление режимами: user mode и kernel mode
+
+Поток может находиться в двух режимах:
+
+- **Пользовательский режим** – доступ к ограниченному набору инструкций и виртуальной памяти. Приложения выполняются именно здесь.
+- **Режим ядра** – полный доступ к оборудованию и системным структурам. Переход происходит при системных вызовах (read, write, open), обработке прерываний или исключениях (ошибка страницы).
+
+Переключение из user mode в kernel mode требует сохранения регистров, переключения таблиц страниц и стека ядра. Этот процесс называется «переключением контекста режима». Современные процессоры поддерживают инструкции syscall/sysret (x86_64) для ускорения перехода.
+
+### Влияние на производительность и многопоточность
+
+Частые переключения между режимами увеличивают накладные расходы. Например, если поток делает много коротких системных вызовов (чтение по 1 байту), он будет постоянно переключать режим, снижая эффективность. Оптимизация: группировка вызовов, использование буферов.
+
+Гибридные модели потоков (N:M) позволяют управлять режимами на уровне библиотеки пользователя, минимизируя входы в ядро. Пример – библиотека Go (горутины), где планировщик работает в user space.
+
+### Пример настройки параметров ядра Linux
+
+В Linux можно влиять на управление потоками через файлы `/proc/sys/kernel/sched_*`:
+- `sched_min_granularity_ns` – минимальный квант времени.
+- `sched_wakeup_granularity_ns` – задержка перед вытеснением при пробуждении потока.
+Команда `chrt` задаёт политику планирования (SCHED_FIFO, SCHED_RR, SCHED_OTHER).
+
+### Заключение
+
+Грамотное управление режимами потоков позволяет достичь баланса между отзывчивостью системы и пропускной способностью. Разработчику важно понимать, как планировщик ОС принимает решения, чтобы писать эффективные многопоточные приложения. Выбор алгоритма и настройка параметров должны соответствовать характеру нагрузки: для серверов – высокая пропускная способность, для десктопов – минимальная задержка.

+ 348 - 0
Лекции/2.5.1200_Управление_режимом_потоков/Gurkin.py

@@ -0,0 +1,348 @@
+import pygame
+import sys
+import random
+
+# Инициализация Pygame
+pygame.init()
+WIDTH, HEIGHT = 1024, 768
+screen = pygame.display.set_mode((WIDTH, HEIGHT))
+pygame.display.set_caption("Диспетчер потоков – управление режимами")
+clock = pygame.time.Clock()
+
+# Шрифты
+FONT_TITLE = pygame.font.Font(None, 48)
+FONT = pygame.font.Font(None, 36)
+FONT_SMALL = pygame.font.Font(None, 28)
+
+# Цвета
+BG = (20, 25, 45)
+QUEUE_BG = (35, 45, 65)
+TEXT_COL = (255, 255, 255)
+BUTTON_COL = (70, 130, 200)
+BUTTON_HOVER = (100, 160, 240)
+ACTIVE_COL = (255, 80, 80)
+MODAL_BG = (0, 0, 0, 200)
+
+# ---------- Класс потока ----------
+class Thread:
+    def __init__(self, tid, priority, burst):
+        self.tid = tid
+        self.priority = priority
+        self.remaining = burst
+        self.base_color = (random.randint(100, 220), random.randint(100, 220), 255)
+        self.animation_progress = 0.0   # 0..1 для анимации выезда
+
+    def get_color(self, is_active=False, pulse=0):
+        if is_active:
+            # Пульсирующий красный
+            r = ACTIVE_COL[0] + int(pulse * 50)
+            g = ACTIVE_COL[1] - int(pulse * 30)
+            b = ACTIVE_COL[2] - int(pulse * 30)
+            return (min(255, r), max(50, g), max(50, b))
+        return self.base_color
+
+# ---------- Планировщик ----------
+class Scheduler:
+    def __init__(self, algorithm):
+        self.algorithm = algorithm   # "rr" или "priority"
+        self.queue = []
+        self.current = None
+        self.time_quantum = 3
+        self.quantum_counter = 0
+        self.interrupts_handled = 0
+        self.total_steps = 0
+
+    def add_thread(self, thread):
+        thread.animation_progress = 0.0
+        self.queue.append(thread)
+
+    def step(self):
+        self.total_steps += 1
+        if self.current is None:
+            if not self.queue:
+                return False
+            self.current = self.queue.pop(0)
+            self.quantum_counter = 0
+            return True
+
+        self.current.remaining -= 1
+        self.quantum_counter += 1
+
+        if self.current.remaining <= 0:
+            self.current = None
+            self.quantum_counter = 0
+        elif self.algorithm == "rr" and self.quantum_counter >= self.time_quantum:
+            self.queue.append(self.current)
+            self.current = None
+            self.quantum_counter = 0
+        elif self.algorithm == "priority":
+            higher = [t for t in self.queue if t.priority < self.current.priority]
+            if higher:
+                self.queue.append(self.current)
+                self.current = None
+                self.quantum_counter = 0
+        return True
+
+    def all_finished(self):
+        return self.current is None and len(self.queue) == 0
+
+# ---------- Вспомогательные функции отрисовки ----------
+def draw_button(text, x, y, w, h, color=None, hover_color=None):
+    if color is None:
+        color = BUTTON_COL
+    if hover_color is None:
+        hover_color = BUTTON_HOVER
+    mouse = pygame.mouse.get_pos()
+    click = pygame.mouse.get_pressed()
+    is_hover = (x < mouse[0] < x + w and y < mouse[1] < y + h)
+    col = hover_color if is_hover else color
+    pygame.draw.rect(screen, col, (x, y, w, h), border_radius=12)
+    pygame.draw.rect(screen, (0, 0, 0), (x + 2, y + 2, w, h), border_radius=12, width=1)
+    text_surf = FONT_SMALL.render(text, True, TEXT_COL)
+    screen.blit(text_surf, (x + w // 2 - text_surf.get_width() // 2, y + h // 2 - text_surf.get_height() // 2))
+    return is_hover and click[0]
+
+def draw_queue_animated(threads, current, pulse):
+    start_x = 80
+    start_y = 180
+    slot_w = 140
+    slot_h = 80
+    max_visible = 6
+
+    pygame.draw.rect(screen, QUEUE_BG, (50, start_y - 20, WIDTH - 100, 130), border_radius=15)
+
+    for i, thr in enumerate(threads[:max_visible]):
+        # Анимация выезда
+        if thr.animation_progress < 1.0:
+            thr.animation_progress = min(1.0, thr.animation_progress + 0.1)
+        offset = int((1 - thr.animation_progress) * slot_w)
+        x = start_x + i * slot_w - offset
+        y = start_y
+        rect = pygame.Rect(x, y, slot_w - 10, slot_h)
+        color = thr.get_color(False)
+        pygame.draw.rect(screen, color, rect, border_radius=10)
+        pygame.draw.rect(screen, (255, 255, 255), rect, width=2, border_radius=10)
+        text = FONT_SMALL.render(f"T{thr.tid} P:{thr.priority} {thr.remaining}", True, TEXT_COL)
+        screen.blit(text, (rect.x + 5, rect.y + 30))
+
+    if current:
+        # Пульсация активного потока
+        scale = 1 + pulse * 0.05
+        w = int(160 * scale)
+        h = int(80 * scale)
+        x = WIDTH // 2 - w // 2
+        y = start_y - 70 - int(pulse * 5)
+        color = current.get_color(True, pulse)
+        rect = pygame.Rect(x, y, w, h)
+        pygame.draw.rect(screen, color, rect, border_radius=15)
+        pygame.draw.rect(screen, (255, 255, 200), rect, width=3, border_radius=15)
+        text = FONT.render(f"Активен: T{current.tid} (ост.{current.remaining})", True, TEXT_COL)
+        screen.blit(text, (rect.x + rect.w // 2 - text.get_width() // 2, rect.y + rect.h // 2 - text.get_height() // 2))
+
+def modal_interrupt(scheduler):
+    """Модальное окно выбора обработки прерывания"""
+    modal_w, modal_h = 450, 220
+    modal_x = WIDTH // 2 - modal_w // 2
+    modal_y = HEIGHT // 2 - modal_h // 2
+
+    overlay = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA)
+    overlay.fill((0, 0, 0, 180))
+    screen.blit(overlay, (0, 0))
+
+    pygame.draw.rect(screen, (50, 55, 80), (modal_x, modal_y, modal_w, modal_h), border_radius=20)
+    pygame.draw.rect(screen, (100, 130, 200), (modal_x, modal_y, modal_w, modal_h), width=3, border_radius=20)
+    title = FONT.render("⚠ Внешнее прерывание!", True, (255, 220, 100))
+    screen.blit(title, (modal_x + modal_w // 2 - title.get_width() // 2, modal_y + 30))
+    sub = FONT_SMALL.render("Переход в режим ядра. Что делать?", True, TEXT_COL)
+    screen.blit(sub, (modal_x + modal_w // 2 - sub.get_width() // 2, modal_y + 70))
+
+    btn_imm = draw_button("Обработать немедленно", modal_x + 30, modal_y + 140, 180, 45)
+    btn_delay = draw_button("Отложить", modal_x + 240, modal_y + 140, 180, 45)
+    pygame.display.flip()
+
+    while True:
+        for event in pygame.event.get():
+            if event.type == pygame.QUIT:
+                pygame.quit()
+                sys.exit()
+            if event.type == pygame.MOUSEBUTTONDOWN:
+                if btn_imm:
+                    return True
+                if btn_delay:
+                    return False
+        # Обновляем состояние кнопок
+        btn_imm = draw_button("Обработать немедленно", modal_x + 30, modal_y + 140, 180, 45)
+        btn_delay = draw_button("Отложить", modal_x + 240, modal_y + 140, 180, 45)
+        pygame.display.flip()
+        clock.tick(30)
+
+# ---------- Основная функция ----------
+def main():
+    scene = 0            # 0-выбор алгоритма, 1-добавление потоков, 2-диспетчеризация, 3-прерывание (модальное), 4-статистика
+    algorithm = None
+    scheduler = None
+    next_tid = 1
+    message = ""
+    step_count = 0
+    interrupt_available = False
+    threads_added = []
+    running = True
+    pulse = 0.0
+    pulse_dir = 1
+
+    while running:
+        # Пульсация для активного потока
+        pulse += 0.05 * pulse_dir
+        if pulse >= 1.0:
+            pulse = 1.0
+            pulse_dir = -1
+        elif pulse <= 0.0:
+            pulse = 0.0
+            pulse_dir = 1
+
+        screen.fill(BG)
+
+        # Заголовок
+        title = FONT_TITLE.render("⚙ Управление режимом потоков", True, TEXT_COL)
+        screen.blit(title, (WIDTH // 2 - title.get_width() // 2, 20))
+
+        # ------------------ СЦЕНА 0: ВЫБОР АЛГОРИТМА ------------------
+        if scene == 0:
+            prompt = FONT.render("Выберите алгоритм планирования:", True, TEXT_COL)
+            screen.blit(prompt, (WIDTH // 2 - prompt.get_width() // 2, 180))
+            if draw_button("Round Robin", WIDTH // 2 - 180, 280, 160, 60):
+                algorithm = "rr"
+                scheduler = Scheduler("rr")
+                scene = 1
+                threads_added = []
+                next_tid = 1
+            if draw_button("Приоритетное", WIDTH // 2 + 20, 280, 160, 60):
+                algorithm = "priority"
+                scheduler = Scheduler("priority")
+                scene = 1
+                threads_added = []
+                next_tid = 1
+            if draw_button("Выход", WIDTH - 120, HEIGHT - 70, 100, 50):
+                running = False
+
+        # ------------------ СЦЕНА 1: ДОБАВЛЕНИЕ ПОТОКОВ ------------------
+        elif scene == 1:
+            info = FONT_SMALL.render("Добавьте минимум 3 потока (случайные параметры)", True, TEXT_COL)
+            screen.blit(info, (WIDTH // 2 - info.get_width() // 2, 120))
+            if draw_button("+ Добавить поток", WIDTH - 200, HEIGHT - 100, 180, 50):
+                new = Thread(next_tid, random.randint(1, 5), random.randint(4, 12))
+                scheduler.add_thread(new)
+                threads_added.append(new)
+                next_tid += 1
+                message = f"✅ Поток T{new.tid} (приор.{new.priority}, burst {new.remaining}) добавлен"
+
+            # Список добавленных потоков
+            y = 200
+            for thr in threads_added:
+                txt = FONT_SMALL.render(f"T{thr.tid} | Приоритет: {thr.priority} | Остаток: {thr.remaining}", True, TEXT_COL)
+                screen.blit(txt, (60, y))
+                pygame.draw.circle(screen, thr.base_color, (40, y + 12), 10)
+                y += 45
+
+            if len(threads_added) >= 3:
+                if draw_button("▶ Запустить планирование", WIDTH // 2 - 120, HEIGHT - 100, 240, 50):
+                    scene = 2
+                    step_count = 0
+                    interrupt_available = False
+
+            # Сообщение и кнопка назад
+            msg_surf = FONT_SMALL.render(message, True, (200, 220, 100))
+            screen.blit(msg_surf, (50, HEIGHT - 60))
+            if draw_button("Назад", 50, HEIGHT - 60, 100, 45):
+                scene = 0
+
+        # ------------------ СЦЕНА 2: ДИСПЕТЧЕРИЗАЦИЯ ------------------
+        elif scene == 2:
+            draw_queue_animated(scheduler.queue, scheduler.current, pulse)
+
+            if draw_button("⏩ Шаг (квант)", WIDTH - 200, HEIGHT - 100, 170, 55):
+                scheduler.step()
+                step_count += 1
+                if scheduler.all_finished():
+                    scene = 4
+
+            if step_count >= 4 and not interrupt_available:
+                if draw_button("⚠ ПРЕРЫВАНИЕ", WIDTH - 200, HEIGHT - 180, 170, 50, (180, 60, 60), (220, 80, 80)):
+                    scene = 3
+
+            info_text = FONT_SMALL.render(f"Шагов: {step_count} | Алгоритм: {'RR' if algorithm == 'rr' else 'Priority'}", True, TEXT_COL)
+            screen.blit(info_text, (30, HEIGHT - 50))
+            if draw_button("Выход", WIDTH - 100, 20, 80, 40):
+                running = False
+
+        # ------------------ СЦЕНА 3: ОБРАБОТКА ПРЕРЫВАНИЯ (МОДАЛЬНОЕ ОКНО) ------------------
+        elif scene == 3:
+            immediate = modal_interrupt(scheduler)
+            if immediate:
+                if scheduler.current:
+                    old = scheduler.current.priority
+                    scheduler.current.priority = max(1, scheduler.current.priority - 2)
+                    scheduler.interrupts_handled += 1
+                    message = f"✅ Прерывание обработано! Приоритет T{scheduler.current.tid} повышен с {old} до {scheduler.current.priority}"
+                else:
+                    message = "Прерывание, но нет активного потока"
+            else:
+                message = "⏸ Прерывание отложено. Эффективность снижена."
+            interrupt_available = True
+            scene = 2
+
+        # ------------------ СЦЕНА 4: ФИНАЛЬНАЯ СТАТИСТИКА ------------------
+        elif scene == 4:
+            if scheduler.interrupts_handled > 0:
+                grade = "A (Отлично)"
+                grade_color = (100, 255, 100)
+            elif step_count < 10:
+                grade = "B (Хорошо)"
+                grade_color = (200, 255, 100)
+            elif step_count < 20:
+                grade = "C (Удовлетворительно)"
+                grade_color = (255, 200, 100)
+            else:
+                grade = "D (Низкая эффективность)"
+                grade_color = (255, 120, 120)
+
+            stats = [
+                "📊 Статистика игры",
+                f"Алгоритм: {'Round Robin' if algorithm == 'rr' else 'Приоритетное (вытеснение)'}",
+                f"Всего шагов (квантов): {step_count}",
+                f"Прерываний обработано немедленно: {scheduler.interrupts_handled}",
+                f"Потоков завершено: {next_tid - 1}",
+                f"Оценка: {grade}"
+            ]
+            y = 180
+            for line in stats:
+                if "Оценка:" in line:
+                    txt = FONT.render(line, True, grade_color)
+                else:
+                    txt = FONT.render(line, True, TEXT_COL)
+                screen.blit(txt, (WIDTH // 2 - txt.get_width() // 2, y))
+                y += 55
+
+            if draw_button("🔄 Сыграть снова", WIDTH // 2 - 180, HEIGHT - 140, 160, 55):
+                scene = 0
+                algorithm = None
+                scheduler = None
+                threads_added = []
+                next_tid = 1
+                step_count = 0
+                interrupt_available = False
+            if draw_button("❌ Выход", WIDTH // 2 + 20, HEIGHT - 140, 160, 55):
+                running = False
+
+        pygame.display.flip()
+        clock.tick(30)
+
+        for event in pygame.event.get():
+            if event.type == pygame.QUIT:
+                running = False
+
+    pygame.quit()
+    sys.exit()
+
+if __name__ == "__main__":
+    main()

+ 109 - 0
Лекции/2.5.1200_Управление_режимом_потоков/Gurkin_czen.md

@@ -0,0 +1,109 @@
+# Сценарий интерактивной игры «Диспетчер потоков: управление режимами»
+
+## Общая концепция
+
+Игрок выступает в роли планировщика операционной системы. Его задача – настроить алгоритм диспетчеризации, добавить потоки и управлять их выполнением, правильно реагируя на прерывания. Игра демонстрирует принципы управления режимами потоков (пользовательский режим / режим ядра), переключение контекста и работу разных алгоритмов планирования.
+
+---
+
+## Сцена 1. Старт и выбор алгоритма
+
+**Элементы сцены:**
+- Три кнопки: «Round Robin», «Приоритетное (с вытеснением)», «Выход».
+- Текстовое описание задания: «Выберите алгоритм планирования потоков».
+- Индикатор текущего времени (не влияет на механику, только атмосфера).
+
+**Действия игрока:**
+- Нажать на одну из кнопок выбора алгоритма.
+- При нажатии «Выход» игра закрывается.
+
+**Условия перехода к следующей сцене:**
+- Алгоритм выбран – игра переходит к Сцене 2 (добавление потоков).
+
+---
+
+## Сцена 2. Добавление потоков
+
+**Элементы сцены:**
+- Кнопка «+ Поток» – создаёт новый поток со случайными параметрами (ID, приоритет 1–5, остаток CPU burst 4–12).
+- Список (таблица) добавленных потоков с полями: ID, приоритет, остаток времени.
+- Кнопка «Запустить планирование» (изначально неактивна, активируется при добавлении не менее 3 потоков).
+- Кнопка «Назад» (возврат к выбору алгоритма).
+- Область сообщений: «Добавлен поток T1», «Добавлен поток T2» и т.д.
+
+**Действия игрока:**
+- Нажимать «+ Поток» до тех пор, пока не появится минимум 3 потока.
+- При желании добавить больше потоков (максимум не ограничен, но для интерфейса рекомендуется не более 8 для наглядности).
+- Нажать «Запустить планирование», когда готов.
+
+**Условия перехода к следующей сцене:**
+- Добавлено 3 или более потоков И нажата кнопка «Запустить планирование» – переход к Сцене 3 (диспетчеризация).
+
+---
+
+## Сцена 3. Диспетчеризация (основной игровой процесс)
+
+**Элементы сцены:**
+- Визуальная очередь готовых потоков – цветные прямоугольники с подписями «T[ID] (ост.X)».
+- Область активного потока – выделяется мигающим красным контуром.
+- Кнопка «Шаг (квант)» – выполняет один квант времени.
+- Счётчик шагов (сколько квантов уже выполнено).
+- Кнопка «Выход» (завершает игру).
+- Область сообщений (например, «Поток T2 выполнил квант, осталось 5 тактов»).
+
+**Действия игрока:**
+- Многократно нажимать «Шаг (квант)», наблюдая за изменением очереди и активного потока.
+- Если выбран Round Robin: каждые 3 шага текущий поток уходит в конец очереди.
+- Если выбрано приоритетное: при появлении потока с более высоким приоритетом (меньшее число) происходит вытеснение – текущий поток сохраняется, а новый становится активным.
+
+**Условия перехода к следующей сцене:**
+- Игрок выполнил не менее 4 шагов – появляется дополнительная кнопка «Прерывание!» (переход к Сцене 4 не автоматический, а по желанию игрока; при этом сама игра остаётся в Сцене 3, но прерывание становится доступным).
+
+*Особое условие:* если все потоки завершились (остаток времени стал 0 у всех) – игра переходит к финальной Сцене 5 (статистика и завершение).
+
+---
+
+## Сцена 4. Обработка прерывания (внутри Сцены 3)
+
+**Элементы сцены (появляются поверх Сцены 3 при нажатии кнопки «Прерывание!»):**
+- Всплывающее окно (диалог) с текстом: «Внешнее прерывание! Переход в режим ядра. Что делать?»
+- Две кнопки: «Обработать немедленно» и «Отложить».
+
+**Действия игрока:**
+- Выбрать один из вариантов.
+
+**Результат выбора:**
+- «Обработать немедленно» – приоритет текущего потока повышается на 2 (число уменьшается, минимум 1). Выводится сообщение: «Прерывание обработано! Приоритет потока T[X] повышен».
+- «Отложить» – прерывание игнорируется, но в статистике это будет отмечено как штраф (в финальной сцене снижается оценка).
+
+**Условие возврата к основной игре:**
+- После выбора всплывающее окно закрывается, игра возвращается к Сцене 3 (диспетчеризация). Счётчик прерываний увеличивается.
+
+---
+
+## Сцена 5. Финальная статистика и завершение
+
+**Элементы сцены:**
+- Текстовый отчёт с параметрами:
+  - Выбранный алгоритм.
+  - Количество обработанных потоков.
+  - Общее количество шагов (квантов).
+  - Количество обработанных прерываний (и сколько из них – немедленно).
+  - Оценка эффективности (A, B, C, D, F) на основе среднего времени ожидания (упрощённо: если прерывания обрабатывались сразу – выше оценка).
+- Кнопка «Сброс» – возвращает в Сцену 1 (выбор алгоритма).
+- Кнопка «Выход» – закрывает приложение.
+
+**Действия игрока:**
+- Ознакомиться со статистикой.
+- Нажать «Сброс» для новой игры или «Выход» для завершения.
+
+**Условие завершения игры:**
+- Нажата кнопка «Выход» – приложение закрывается.
+
+---
+
+## Примечания к реализации
+
+- Сцена 4 технически может быть реализована как модальное окно, не требующее отдельной сцены, но по условию задания «Сцена» – это этап игры, поэтому описан переход на отдельный экран обработки прерывания с возвратом.
+- Минимальное количество сцен – 5 (сцены 1, 2, 3, 4, 5). Сцена 3 и сцена 4 логически связаны, но считаются разными этапами.
+- Все визуальные элементы должны соответствовать тёмной теме и иметь анимации (по ТЗ).

+ 114 - 0
Лекции/2.5.1200_Управление_режимом_потоков/Gurkin_tech_zd.md

@@ -0,0 +1,114 @@
+# Техническое задание
+## на разработку обучающей игры «Диспетчер потоков: управление режимами»
+
+### 1. Общие сведения
+
+**Название проекта:** «Диспетчер потоков: управление режимами» (Thread Scheduler Simulator)
+
+**Назначение:** Обучающее ПО для демонстрации алгоритмов планирования потоков в операционных системах, переключения между пользовательским режимом и режимом ядра, а также обработки прерываний.
+
+**Целевая аудитория:** Студенты IT-направлений, преподаватели курсов по операционным системам, разработчики многопоточных приложений.
+
+**Платформа реализации:**  
+- Язык программирования: Python 3.8 и выше.  
+- Графическая библиотека: Pygame 2.5.  
+- Поддерживаемые ОС: Windows 10/11, Ubuntu 20.04+, macOS 11+.  
+- Минимальные требования: 2 ГБ ОЗУ, процессор от 1.5 ГГц, разрешение экрана от 1024×768.
+
+---
+
+### 2. Функциональные требования
+
+**2.1. Выбор алгоритма планирования**  
+При запуске игрок видит две кнопки: «Round Robin» и «Приоритетное (с вытеснением)». Выбор определяет поведение планировщика на протяжении всей игры.
+
+**2.2. Управление потоками**  
+После выбора алгоритма появляется интерфейс добавления потоков. Кнопка «+ Поток» создаёт новый поток со следующими случайными параметрами:  
+- уникальный идентификатор (ID);  
+- приоритет от 1 до 5 (1 – наивысший);  
+- остаток процессорного времени (CPU burst) от 4 до 12 тактов.  
+Игрок может добавить любое количество потоков, но для перехода к симуляции необходимо минимум три потока.
+
+**2.3. Отображение очереди и активного потока**  
+Все добавленные потоки показываются в виде цветных прямоугольников. На каждом прямоугольнике подпись: «T[ID] (ост. X)». Текущий выполняемый поток выделяется красным мигающим контуром или заливкой. Очередь визуально обновляется после каждого шага.
+
+**2.4. Пошаговое выполнение**  
+Кнопка «Шаг (квант)» запускает один шаг планировщика.  
+- Для Round Robin: поток выполняется 3 такта (квант), после чего перемещается в конец очереди, если не завершился раньше.  
+- Для приоритетного алгоритма: каждый такт проверяется наличие потока с более высоким приоритетом (меньшим числом). Если такой есть – текущий поток вытесняется и помещается в начало очереди (или в конец – на усмотрение реализации, но вытеснение должно быть заметно).
+
+**2.5. Эмуляция прерывания**  
+После того как игрок сделал не менее четырёх шагов, появляется кнопка «Прерывание!». При её нажатии имитируется внешнее прерывание (переход в режим ядра). Эффект: приоритет текущего потока повышается на 2 (числовое значение уменьшается на 2, но не ниже 1). На экран выводится сообщение: «Прерывание обработано! Приоритет потока T[X] повышен».
+
+**2.6. Завершение игры**  
+Когда все потоки исчерпали свой остаток процессорного времени, появляется сообщение «Все потоки завершены! Игра пройдена» и кнопка «Выход». Также кнопка «Выход» доступна на любом этапе для принудительного закрытия.
+
+---
+
+### 3. Нефункциональные требования
+
+**3.1. Производительность**  
+Частота кадров должна быть не ниже 30 FPS при работе с 10 потоками. Отклик на нажатие кнопок – мгновенный (без заметных задержек).
+
+**3.2. Надёжность**  
+Программа не должна завершаться аварийно при некорректных действиях пользователя, например при попытке сделать шаг, когда очередь пуста, или при нажатии на кнопку до выбора алгоритма.
+
+**3.3. Удобство использования**  
+Всё управление осуществляется мышью. Кнопки имеют эффект наведения (меняют цвет). Текст сообщений (о добавлении потока, о прерывании, о завершении) выводится в специальной области экрана.
+
+**3.4. Требования к графике и анимациям**  
+- Тёмная цветовая схема (фон тёмно-синий, элементы очереди – яркие контрастные цвета).  
+- Скруглённые углы кнопок и прямоугольников потоков.  
+- Пульсация активного потока (плавное изменение яркости или мигание).  
+- Плавное обновление очереди (при удалении завершённого потока остальные сдвигаются).
+
+**3.5. Расширяемость**  
+Код должен позволять легко добавлять новые алгоритмы планирования (например, FCFS или многоуровневые очереди). Для этого параметры вроде кванта времени и диапазонов приоритетов выносятся в константы в начале файла.
+
+**3.6. Совместимость**  
+Использовать только кроссплатформенные возможности Pygame. Избегать системно-зависимых вызовов.
+
+---
+
+### 4. Архитектура приложения
+
+Проект состоит из одного Python-скрипта. В нём реализованы:
+
+- **Класс Thread** – хранит ID, приоритет, оставшееся время, цвет для отрисовки.
+- **Класс Scheduler** – управляет очередью потоков, текущим потоком, алгоритмом, счётчиком кванта. Содержит методы `add_thread` и `step` (основная логика планирования).
+- **Функции отрисовки** – `draw_button` (рисует кнопку и возвращает True при нажатии), `draw_queue` (отображает очередь и активный поток), `draw_message` (вывод сообщений в нижней части экрана).
+- **Главный цикл** – обрабатывает события Pygame, управляет сценами (0 – выбор алгоритма, 1 – добавление потоков, 2 – симуляция), вызывает функции отрисовки и обновляет экран.
+
+Логика работы: сцена 0 → выбор алгоритма → сцена 1 → добавление не менее 3 потоков → сцена 2 → пошаговое выполнение с возможностью прерывания → завершение.
+
+---
+
+### 5. Состав документации и поставки
+
+Вместе с программой поставляются следующие файлы в формате Markdown:
+
+- `lecture.md` – лекция по теме «Управление режимом потоков» объёмом около 650 слов, без орфографических ошибок, с оригинальностью выше 50%.
+- `questions.md` – пять вопросов для самопроверки, каждый с четырьмя вариантами ответа, правильный ответ выделен полужирным шрифтом.
+- `scenario.md` – сценарий интерактивной игры из пяти сцен, с описанием элементов, действий и условий перехода.
+- `thread_scheduler_game.py` – исполняемый код на Python с графическим интерфейсом.
+- `technical_specification.md` – настоящее техническое задание.
+
+Инструкция по запуску: установить Python, выполнить `pip install pygame`, затем запустить скрипт командой `python thread_scheduler_game.py`.
+
+---
+
+### 6. Критерии приёмки
+
+- Программа успешно запускается на целевой ОС без ошибок.
+- Реализованы все функциональные требования: выбор алгоритма, добавление потоков, пошаговое выполнение, прерывание после четырёх шагов, корректное завершение.
+- Присутствуют анимации (мигание активного потока, эффекты наведения кнопок).
+- Исходный код соответствует стандарту PEP 8, содержит комментарии к сложным участкам.
+- Лекция содержит более 600 слов, орфографических ошибок менее 2%, не является копией готовых источников.
+- Сценарий игры включает минимум пять сцен с чёткими условиями перехода.
+- Вопросы оформлены согласно варианту №1: каждый вопрос с новой строки, ответы – ниже, правильный ответ полужирный, вопросы разделены пустой строкой.
+
+---
+
+### 7. Примечания
+
+Данное техническое задание является итоговым документом для разработки. Все изменения согласовываются с заказчиком. В будущем возможно расширение функционала: добавление графиков эффективности, звукового сопровождения, сохранения результатов. Текущая версия предназначена для демонстрации базовых концепций управления потоками в игровой форме.

+ 29 - 0
Лекции/2.5.1200_Управление_режимом_потоков/Gurkin_voprosi.md

@@ -0,0 +1,29 @@
+Какой алгоритм планирования использует фиксированный квант времени для каждого потока?
+- FCFS
+- **Round Robin**
+- Приоритетное (без вытеснения)
+- Многоуровневая очередь
+
+Что происходит при переходе потока из пользовательского режима в режим ядра?
+- **Системный вызов или прерывание**
+- Вытеснение по времени
+- Завершение потока
+- Увеличение кванта
+
+Какой недостаток характерен для алгоритма FCFS?
+- Голодание низкоприоритетных потоков
+- **Эффект конвоя**
+- Сложность реализации
+- Отсутствие вытеснения – это достоинство
+
+Что такое контекстное переключение?
+- Смена активного окна приложения
+- **Сохранение состояния одного потока и загрузка состояния другого**
+- Переключение между пользовательским режимом и режимом ядра
+- Изменение приоритета потока
+
+Какая техника предотвращает голодание в приоритетном планировании?
+- Квантование времени
+- **Старение приоритетов**
+- Многоуровневые очереди
+- Вытеснение по прерыванию