Процессор под нагрузкой превращает электричество в тепло, и когда отвод не справляется, падает частота, а с ней и производительность. В Linux этим управляет подсистема ядра: она измеряет температуру, сравнивает ее с порогами и сама снижает нагрев. Из коробки настройка усредненная: ноутбук сбрасывает частоту раньше времени, сервер доползает до критических порогов, а администратор узнает об этом по бенчмарку. Дальше разбираются тепловые зоны sysfs, пороги срабатывания, алгоритмы охлаждения, частотные governors, потолок частоты и принудительный простой драйвера intel_powerclamp. Все команды выполняются в одной сессии терминала и не требуют пересборки ядра, а к концу складывается цикл: измерить, найти виновника, ограничить и закрепить настройку.

Тепловые зоны ядра и файлы sysfs, где живет температура

Ядро представляет каждый датчик тепловой зоной, а каталог /sys/class/thermal перечисляет их все: thermal_zone0, thermal_zone1 и далее. Внутри зоны два главных файла: type с именем датчика и temp с показанием в миллиградусах Цельсия, то есть 45000 означает ровно 45 градусов. На типичной x86-системе зон несколько: acpitz приходит из ACPI-таблиц BIOS, x86_pkg_temp отражает температуру процессорного корпуса, на ноутбуках добавляется датчик радиомодуля iwlwifi. Процессорные ядра видны и через подсистему hwmon, где драйвер coretemp публикует файлы temp1_input, оттуда читает и команда sensors из пакета lm-sensors.

cat /sys/class/thermal/thermal_zone0/type
cat /sys/class/thermal/thermal_zone0/temp
x86_pkg_temp
45000

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

grep . /sys/class/thermal/thermal_zone*/type
/sys/class/thermal/thermal_zone0/type:x86_pkg_temp
/sys/class/thermal/thermal_zone1/type:acpitz

Рядом живут cooling devices, устройства, которыми зона охлаждается, с файлами type, cur_state и max_state. Тип Processor означает охладитель частоты, тип intel_powerclamp программный простой из отдельного раздела ниже.

Пороги trip_point и четыре уровня охлаждения от вентилятора до отключения питания

Каждая зона несет пороги в файлах trip_point_0_temp, trip_point_1_temp и далее, а тип срабатывания лежит рядом в trip_point_0_type. Типов четыре: active запускает вентилятор на заданную скорость, passive включает программное охлаждение со снижением частоты, hot предупреждает о близости предела, critical требует немедленного отключения питания машины. Значения в тех же миллиградусах: у активного порога на настольной плате типично 60 градусов, passive на ноутбуке обычно в диапазоне 85-95, критический на процессорном датчике порядка 100-105, в файлах это числа вроде 105000. Рядом лежит trip_point_0_hyst, гистерезис, на сколько температура должна опуститься, чтобы охлаждение отпустило, иначе вентилятор дергался бы каждые пару секунд.

grep . /sys/class/thermal/thermal_zone0/trip_point_*_type
grep . /sys/class/thermal/thermal_zone0/trip_point_*_temp
/sys/class/thermal/thermal_zone0/trip_point_0_type:active
/sys/class/thermal/thermal_zone0/trip_point_1_type:passive
/sys/class/thermal/thermal_zone0/trip_point_0_temp:60000
/sys/class/thermal/thermal_zone0/trip_point_1_temp:85000

Пересечение passive порога внешне почти незаметно: в журнал падают сообщения ядра, а частота в scaling_cur_freq резко проседает. Счетчики копятся в /sys/devices/system/cpu/cpu0/thermal_throttle/package_throttle_count, поиск в журнале занимает секунды:

cat /sys/devices/system/cpu/cpu0/thermal_throttle/package_throttle_count
journalctl -k | grep -i throttled

Характерная строка:

CPU2: Package temperature above threshold, cpu clock throttled (total events = 17)

Если счетчик растет на простаивающей машине, виновато охлаждение: забитый радиатор, остановившийся вентилятор или высохшая паста.

Политики охлаждения step_wise и fair_share вместе со службой thermald

Насколько агрессивно охлаждать, решает алгоритм зоны: текущее имя видно в файле policy, полный список в available_policies. Стандартный набор такой: step_wise поднимает охлаждение ступенями и так же плавно отпускает, fair_share распределяет усилие между привязанными охладителями по весам, power_allocator делит между устройствами бюджет мощности в милливаттах и чаще встречается на ARM-платах, user_space отдает политику пользовательскому коду.

cat /sys/class/thermal/thermal_zone0/policy
cat /sys/class/thermal/thermal_zone0/available_policies
step_wise
user_space step_wise fair_share power_allocator

Пользовательским кодом на ноутбуках Intel обычно становится служба thermald: она читает ограничения из таблиц BIOS, держит температуру около целевой, реагирует быстрее step_wise, проверяется командой systemctl status thermald. Привязку охладителей подсказывают файлы cdev0 и cdev1 внутри каталога зоны. Без нее, например на сервере, зона работает под step_wise, охлаждение остается, просто без подстройки под модель устройства.

Частотные governors schedutil и performance как первая линия обороны

Температура ядра прямо следует за частотой, поэтому главный рычаг сидит в /sys/devices/system/cpu/cpu0/cpufreq. Файл scaling_governor выбирает политику: performance держит максимум постоянно и греет чип даже в простое, powersave прижимает к минимуму ценой отзывчивости, ondemand и conservative опрашивают загрузку по таймеру с порогом up_threshold, по умолчанию 95, а schedutil встроен в планировщик и оценивает нагрузку механизмом PELT по каждому потоку, поднимая частоту ровно под работу. Для настольной машины и сервера разумный дефолт schedutil: он сбрасывает частоту за миллисекунды после окончания задачи и не дает чипу нагреваться без дела. Оговорка одна: задачи реального времени планировщик всегда гоняет на максимуме частоты, governor на них не влияет. Параметр rate_limit_us в микросекундах ограничивает частоту пересчетов, увеличение, например до 5000, сглаживает скачки и частоты, и нагрева. Отдельные ручки оставляет драйвер intel_pstate: no_turbo запрещает частоты turbo выше базовой, max_perf_pct ограничивает верхний предел в процентах от максимума.

cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors
echo schedutil > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
cat /sys/devices/system/cpu/cpufreq/schedutil/rate_limit_us
echo 1 > /sys/devices/system/cpu/intel_pstate/no_turbo
echo 80 > /sys/devices/system/cpu/intel_pstate/max_perf_pct

Если schedutil в списке нет, активен intel_pstate в производительном режиме с одними performance и powersave, режим переключается параметром ядра intel_pstate=passive при загрузке. Текущую частоту показывает scaling_cur_freq, разброс между ядрами под однопоточной задачей наглядно объясняет, как governor расходует бюджет.

Потолок частоты scaling_max_freq и расчет экономии тепла

Когда нужен гарантированный результат, а не тонкая политика, честнее всего ограничить верхнюю частоту. Мощность транзистора растет пропорционально произведению частоты на квадрат напряжения, а напряжение следует за частотой, поэтому срез верхних сотен мегагерц экономит тепло непропорционально сильно. Числовой пример: чип с базой 2.4 ГГц и turbo до 4.0 ГГц урезают до 2.6 ГГц, при этом напряжение опускается с 1.15 В до 0.90 В. Частотный коэффициент 2.6 делить на 4.0 дает 0.65, квадрат отношения напряжений дает 0.61, произведение равно 0.40, то есть в пике выделяется около 40 процентов прежнего тепла, и долгая компиляция проходит без троттлинга. Ограничение пишется в scaling_max_freq каждого ядра, а утилита cpupower делает это разом для всей машины:

cpupower frequency-info | grep -A3 "hardware limits"
cpupower frequency-set -u 2600MHz -d 1200MHz

Первая команда печатает аппаратные границы, вторая срезает потолок до 2.6 ГГц и пол до 1.2 ГГц. Побочный эффект приятный: с обрезанным потолком governor performance просто держит безопасный максимум, отзывчивость сохраняется, а граница нагрева задана жестко. Записи в scaling_max_freq живут только до перезагрузки, поэтому их повторяют в короткой oneshot-службе systemd:

[Unit]
Description=Ограничение частоты процессора для контроля нагрева
[Service]
Type=oneshot
ExecStart=/usr/bin/cpupower frequency-set -u 2600MHz
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target

Файл кладется в /etc/systemd/system/cpu-thermal-cap.service, после чего systemctl daemon-reload и systemctl enable --now cpu-thermal-cap.service закрепляют ограничение навсегда.

Пассивное охлаждение intel_powerclamp для машины без вентилятора

Драйвер intel_powerclamp синхронно вводит принудительный простой во все ядра, чтобы процессор проваливался в пакетные C-состояния, где потребление падает на порядки. Для каждого CPU ядро заводит поток kidle_inject с классом планирования SCHED_FIFO, потоки ходят по циклу пауза-mwait и дозируют простой до долей секунды. Наружу драйвер выступает обычным cooling device с файлами cur_state и max_state: максимум по умолчанию 50, под простой можно отдать не больше половины времени, а параметр модуля max_idle поднимает предел, но не выше 75, если маска cpumask покрывает все процессоры.

for d in /sys/class/thermal/cooling_device*; do grep -H . $d/type; done
echo 25 > /sys/class/thermal/cooling_device14/cur_state
cat /sys/class/thermal/cooling_device14/cur_state

Первая строка находит охладитель с типом intel_powerclamp, в примере это cooling_device14. Запись 25 задает целевой процент простоя, чтение возвращает фактический, включая естественный простой. Ноль останавливает инъекцию, а до первого запуска файл отвечает значением -1, отличая выключенное состояние от честного нуля. Под нагрузкой режим виден в top выросшим процентом id:

Cpu(s): 71.2%us,  4.7%sy, 24.1%id
 3341 root     -51    25 kidle_inject/0
 3352 jacob     20   286 spin

Ограничения честные: если система и так простаивает больше целевого процента, драйвер ничего не делает, шторм прерываний будит ядра и снижает эффект, а большим машинам нужна калибровка, ее ход виден в /sys/kernel/debug/intel_powerclamp/powerclamp_calib. По измерениям разработчиков на восьмиядерной системе поколения Ivy Bridge управляемый простой дал до 40 процентов выигрыша в производительности на ватт по сравнению с отключением ядер. Практическая ниша широкая: ультрабук с шумным кулером, тихий NAS, сценарий с остановившимся вентилятором, когда инъекция 30 процентов простоя удерживает чип ниже passive порога.

Нагрузочный тест, автозапуск настроек и порядок первой диагностики

Настройку проверяют синтетической нагрузкой: stress-ng с ключом --cpu 0 берет все ядра, 120 секунд хватает, чтобы температура вышла на плато, а наблюдатель в соседнем терминале печатает все зоны:

stress-ng --cpu 0 --timeout 120
watch -n 1 "cat /sys/class/thermal/thermal_zone*/temp"

Ключ -n 1 у watch задает интервал обновления. Меры сверяют числами: 94 градуса против 81 при удлинении теста на 15 процентов означает, что ограничение работает. Порядок первой диагностики при подозрении на перегрев укладывается в пять шагов:
1. прочитать температуру всех зон командой grep . /sys/class/thermal/thermal_zone*/temp;
2. сравнить цифры с порогами из файлов trip_point_*_temp и найти зону-лидера;
3. посмотреть scaling_governor и scaling_cur_freq, чтобы исключить застрявшую на максимуме частоту;
4. поискать троттлинг в журнале ядра командой journalctl -k | grep -i throttled;
5. только после этого двигать governors, потолок частоты и cooling devices, иначе причина останется невыясненной.

Типичные ошибки повторяются годами: governor performance на ноутбуке греет чип в простое без пользы, запрет turbo не спасает машину с забитым пылью радиатором, где чистка и свежая паста дают больше любых файлов sysfs, разовое чтение temp молчит о динамике, а путаница между active и passive заставляет чинить вентилятор там, где дело в частоте. Полный контур управления собирается коротко: датчики дают цифру, пороги задают границу, алгоритм зоны принимает решение, governors и потолок частоты убирают лишний нагрев, intel_powerclamp дожимает остаток, а служба systemd закрепляет все после перезагрузки. Машина перестает нервничать на пиках, и троттлинг из сюрприза превращается в управляемый параметр с понятной ценой в процентах производительности.