Под капотом · Виртуализация · Работа и остановка

Корректное выключение

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

Команда
virsh shutdown vm1
libvirt API virDomainShutdown(dom) QMP system_powerdown

После выполнения команды гипервизор не убивает ВМ, а нажимает кнопку питания - решение остаётся за гостем.

  • пользователь 1. Пользователь вводит команду выключения
    virDomainShutdown(dom)

    Обычно с таймаутом: если гость не ответил, админ идёт в принудительное выключение.

  • libvirt 2. Демон отправляет ACPI-событие
    {"execute":"system_powerdown"}

    Это эмуляция нажатия кнопки питания, а не команда «заверши процесс».

  • QEMU 3. Событие доставляется гостю
    ACPI event → guest OS

    Без ACPI (или без гостевого агента) гость просто не увидит просьбу.

  • гость 4. Гость выключается по-своему
    остановка сервисов → размонтирование ФС
    → сброс кэшей → poweroff

    Именно поэтому shutdown безопасен: данные доходят до диска штатным путём.

  • QEMU 5. QEMU сообщает о выключении
    {"event":"SHUTDOWN", …}
    # POWERDOWN - когда гость сам инициировал выключение

    Направление важно: команда system_powerdown идёт хосту→гостю, событие - гость→хосту.

  • libvirt 6. Демон освобождает ресурсы
    state → shut off
    снятие: TAP, cgroup, метки, временные файлы

    Конфигурация остаётся на диске - ВМ видна в virsh list --all.

  • QEMU 7. Процесс завершается
    exit → закрытие vcpu fd и vm fd

    Память VM освобождается по последней ссылке на файловый дескриптор (KVM API §2).