Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ГАК-2026.docx
Скачиваний:
1
Добавлен:
16.06.2026
Размер:
2.66 Mб
Скачать

Этап 4: Динамическая компоновка (если нужно)

Если программа использует динамические библиотеки (DLL в Windows, .so в Linux), то в дело вступает динамический компоновщик (dynamic linker/loader).

  • Ядро загружает сам динамический компоновщик (например, /lib/ld-linux.so.2).

  • Компоновщик загружает требуемые библиотеки, связывает символы (разрешает ссылки).

  • В современных системах компоновка тоже ленивая (lazy binding) — символы разрешаются при первом обращении.

Этап 5: Передача управления

Ядро подготавливает стек процесса, записывая туда аргументы командной строки (argv), переменные окружения (envp).

Затем ядро переключает процессор в пользовательский режим и передаёт управление на точку входа программы (обычно это метка _start, которая вызывает main).

Этап 6: Выполнение программы

Программа выполняется в пользовательском режиме. Когда ей нужны ресурсы (открыть файл, выделить память), она вызывает системные вызовы, которые переключают процессор в режим ядра, где запрос обрабатывается.

Этап 7: Завершение программы

Программа завершается:

  • явным вызовом exit() или возвратом из main;

  • получением сигнала (например, SIGKILL);

  • возникновением необрабатываемого исключения.

Ядро:

  • закрывает все открытые файлы;

  • освобождает память;

  • удаляет структуры процесса;

  • уведомляет родительский процесс о завершении.

3. Структура процесса в памяти

Типичное распределение памяти процесса в Linux:

  • Стек — хранит локальные переменные, параметры функций, адреса возврата. Растёт вниз (от высоких адресов к низким).

  • Куча — динамически выделяемая память (malloc/new). Растёт вверх.

  • Сегменты данных — глобальные и статические переменные.

  • Сегмент кода — инструкции процессора (read-only).

4. Состояния процесса

Процесс в течение жизни проходит через несколько состояний:

  • Создание (new) — процесс создаётся, но ещё не готов к выполнению.

  • Готовность (ready) — процесс готов к выполнению и ждёт процессор.

  • Выполнение (running) — процесс выполняется на процессоре.

  • Ожидание (waiting/blocked) — процесс ждёт завершения операции ввода-вывода или получения сигнала.

  • Завершение (terminated) — процесс завершён, но ещё не удалён из таблицы процессов (zombie в Linux).

5. Контекст процесса и переключение контекста

Контекст процесса включает:

  • значения регистров процессора;

  • счётчик команд (PC);

  • указатель стека (SP);

  • информацию о памяти (таблицы страниц);

  • информацию о ресурсах.

Переключение контекста — это процесс остановки одного процесса и запуска другого. Выполняется планировщиком:

  1. Сохранить контекст текущего процесса в его PCB (Process Control Block).

  2. Загрузить контекст следующего процесса из его PCB.

  3. Передать управление новому процессу.

Переключение контекста — относительно дорогая операция (от нескольких сотен до тысяч тактов процессора), поэтому современные ОС стараются минимизировать их частоту.

6. Системные вызовы

Программа взаимодействует с ядром через системные вызовы (system calls).

Примеры системных вызовов в Linux:

  • read(), write() — ввод-вывод;

  • open(), close() — работа с файлами;

  • fork(), exec(), wait() — управление процессами;

  • brk(), mmap() — управление памятью;

  • socket(), connect() — сетевые операции.

Механизм работы:

  1. Программа в user mode кладёт номер системного вызова и аргументы в регистры.

  2. Выполняет инструкцию int 0x80 (в x86) или syscall (в x86-64).

  3. Процессор переключается в режим ядра.

  4. Ядро выполняет запрошенную операцию.

  5. Возвращает результат и переключает обратно в user mode.