Работа с системными вызовами


Цель лабораторной

Понять, как прикладной код взаимодействует с операционной системой через системные вызовы, и научиться:

  • корректно работать с файлами и дескрипторами;
  • обрабатывать ошибки ОС;
  • видеть разницу между POSIX и WinAPI;
  • диагностировать проблемы через трассировку.

Теория в двух абзацах

Системный вызов — переход из пользовательского режима в режим ядра для выполнения привилегированной операции: чтение файла, создание процесса, сетевой ввод-вывод.

Важный принцип: интерфейс может выглядеть одинаково (read, open, CreateFile), но поведение зависит от ОС, файловой системы, прав доступа и текущих лимитов процесса.


Что подготовить

  • Linux/macOS или WSL для POSIX-части.
  • Windows (PowerShell/CMD) для WinAPI-наблюдений.
  • Компилятор C/C++ (или язык с FFI/системными обертками).
  • Инструменты трассировки:
    • strace (Linux),
    • Process Monitor (Windows).

Практикум: пошагово

Шаг 1. Файловый ввод-вывод через системный уровень

Сделайте программу, которая:

  1. Открывает файл.
  2. Записывает данные.
  3. Закрывает дескриптор.
  4. Повторно открывает файл и читает данные.

Проверьте:

  • что все вызовы возвращают успешный код;
  • что при ошибке вы получаете код причины (errno/GetLastError).

Шаг 2. Смоделируйте ошибочные сценарии

Повторите операции с предсказуемыми ошибками:

  • несуществующий путь;
  • отсутствие прав;
  • попытка читать из закрытого дескриптора.

Для каждого сценария зафиксируйте:

  • код ошибки;
  • человекочитаемое описание;
  • как приложение должно реагировать (retry, fallback, прекращение).

Шаг 3. Эксперимент с дескрипторами

Запустите цикл открытия файлов без закрытия (в учебных рамках, с ограничением). Наблюдайте:

  • рост числа открытых дескрипторов;
  • момент достижения лимита;
  • ошибку при превышении лимита.

Сделайте вывод, почему утечки дескрипторов в серверных приложениях критичны.


Шаг 4. Процессы и дочерние задачи

Реализуйте запуск дочернего процесса:

  • POSIX: fork + exec;
  • Windows: CreateProcess.

Отследите:

  • передачу аргументов;
  • код завершения;
  • поведение при зависшем дочернем процессе (таймаут/kill).

Шаг 5. Трассировка реального запуска

Запустите программу под strace или ProcMon и ответьте:

  • какие системные вызовы вызываются чаще всего;
  • где наблюдаются задержки;
  • есть ли лишние повторные открытия/чтения.

Что включить в отчет

  1. Таблицу "операция -> системный вызов -> результат".
  2. Таблицу ошибок и способов обработки.
  3. Скриншоты/логи трассировки.
  4. Краткий разбор различий POSIX и WinAPI по вашему сценарию.

Типичные ошибки новичков

  • Игнорировать коды возврата системных вызовов.
  • Не закрывать дескрипторы в ветках ошибок.
  • Смешивать буферизованный и небезопасный низкоуровневый I/O без понимания последствий.
  • Делать platform-specific код без слоя абстракции.

Практический вывод

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