Глядя на источник, strace
я обнаружил использование флага клонирования, CLONE_IDLETASK
который описан там как:
#define CLONE_IDLETASK 0x00001000 /* kernel-only flag */
После более глубокого изучения я обнаружил, что, хотя этот флаг не охватывается, man clone
он фактически используется ядром во время процесса загрузки для создания незанятых процессов (каждый из которых должен иметь PID 0) для каждого процессора на машине. то есть машина с 8 процессорами будет иметь как минимум 7 (см. вопрос ниже), такие процессы «работают» (обратите внимание на кавычки).
Теперь это приводит меня к вопросу о том, что на самом деле делает этот «простой» процесс. Я предполагаю, что он выполняет операцию NOP непрерывно до тех пор, пока не истечет его временной интервал, и ядро не назначит реальный процесс для повторного запуска или назначения незанятого процесса (если ЦП не используется). Тем не менее, это полное предположение. Так:
На машине с, скажем, 8 процессорами будут созданы 7 таких бездействующих процессов? (и один процессор будет удерживаться самим ядром, пока не будет выполняться пользовательская область?)
Действительно ли простой процесс представляет собой просто бесконечный поток операций NOP? (или цикл, который делает то же самое).
uptime
Рассчитывается ли использование ЦП (скажем ) просто по тому, как долго неактивный процесс был на ЦП и как долго его не было в течение определенного периода времени?
PS Вполне вероятно, что большая часть этого вопроса связана с тем, что я не до конца понимаю, как работает процессор. то есть я понимаю сборку, временные рамки и прерывания, но я не знаю, как, например, процессор может использовать больше или меньше энергии в зависимости от того, что он выполняет. Я был бы признателен, если бы кто-то тоже смог меня просветить.
источник
Ответы:
Неиспользуемая задача используется для учета процессов, а также для снижения энергопотребления. В Linux одна незанятая задача создается для каждого процессора и привязывается к этому процессору; всякий раз, когда на этом процессоре не выполняется никакой другой процесс, задача ожидания назначается. Время, проведенное в неактивных задачах, отображается как «простое» в таких инструментах, как
top
. (Время работы рассчитывается по-разному.)Похоже, что в Unix всегда был какой-то цикл ожидания (но не обязательно в режиме реального времени, см. Ответ Жиля ), и даже в V1 он использовал
WAIT
инструкцию, которая останавливала процессор до тех пор, пока не произошло прерывание (оно означало «ждать прерывание»). Некоторые другие операционные системы использовали циклы занятости, в частности DOS, OS / 2 и ранние версии Windows. В течение достаточно долгого времени процессоры использовали такую инструкцию «ожидания», чтобы снизить потребление энергии и выработку тепла. Вы можете увидеть различные реализации пустых задач, например, вarch/x86/kernel/process.c
ядре Linux: базовая просто вызываетHLT
, который останавливает процессор до тех пор, пока не произойдет прерывание (и включает режим энергосбережения C1), другие реализации обрабатывают различные ошибки или неэффективность ( например, использованиеMWAIT
вместоHLT
некоторых ЦП).Все это полностью отделено от неактивных состояний в процессах, когда они ожидают события (ввод-вывод и т. Д.).
источник
play_dead()
это очень хорошее мнемоническое имя для выполнения HALT. Не было бы риска отправить HALT на каждый процессор и, следовательно, зависнуть? (то есть достижение этой ситуации, остановка каждого процессора, будет ошибкой в ядре?)В проекте учебника планировщика процессов, если у планировщика нет какого-либо процесса для планирования (т. Е. Если все процессы заблокированы, ожидая ввода), тогда планировщик ожидает прерывания процессора. Прерывание может указывать ввод от периферийного устройства (действия пользователя, сетевой пакет, завершенное чтение с диска и т. Д.) Или может быть прерыванием таймера, которое запускает таймер в процессе.
Планировщик Linux не имеет специального кода для ничего не делающего дела. Вместо этого он кодирует случай «ничего не делать» как особый процесс, бездействующий процесс. Процесс бездействия назначается только в том случае, если не запланирован ни один другой процесс (он фактически имеет бесконечно низкий приоритет). Процесс бездействия фактически является частью ядра: это поток ядра, то есть поток, который выполняет код в ядре, а не код в процессе. (Точнее, есть один такой поток для каждого ЦП.) Когда запускается незанятый процесс, он выполняет операцию ожидания прерывания.
Как работает ожидание прерывания, зависит от возможностей процессора. С самым простым дизайном процессора, это просто занятый цикл -
Процессор всегда выполняет инструкцию ветвления, которая ничего не делает. Большинство современных ОС не делают этого, если они не работают на процессоре, где нет ничего лучше, а большинство процессоров имеют что-то лучшее. Вместо того, чтобы тратить энергию, ничего не делая, кроме обогрева комнаты, в идеале процессор должен быть выключен. Таким образом, ядро запускает код, который инструктирует процессор выключать себя или, по крайней мере, выключать большую часть процессора. Должна быть хотя бы одна маленькая деталь, которая остается включенной, контроллер прерываний. Когда периферийное устройство запускает прерывание, контроллер прерываний отправляет сигнал активизации на основной (часть) процессора.
На практике современные процессоры, такие как Intel / AMD и ARM, имеют много сложных настроек управления питанием. ОС может оценить, как долго процессор будет оставаться в режиме ожидания, и будет выбирать различные режимы с низким энергопотреблением в зависимости от этого. Режимы предлагают различные компромиссы между энергопотреблением в режиме ожидания и временем, необходимым для входа и выхода из режима ожидания. На некоторых процессорах ОС также может снизить тактовую частоту процессора, когда обнаружит, что процессы не занимают много процессорного времени.
источник
HLT
мог отключить SL варианты 386 и 486 до выхода DX4 (статья в Википедии неверна).Нет, неработающая задача не тратит циклы ЦП. Планировщик просто не выбирает незанятый процесс для выполнения. Неактивный процесс ожидает какого-то события, чтобы оно могло продолжаться. Например, он может ожидать ввода в
read()
системном вызове.Кстати, ядро не отдельный процесс. Код ядра всегда выполняется в контексте процесса (ну, за исключением особого случая потока ядра), поэтому неверно говорить, что «один процессор будет удерживаться самим ядром, пока не будет выполняться пользовательская область».
источник