Что делает процесс бездействующего процессора?

73

Глядя на источник, straceя обнаружил использование флага клонирования, CLONE_IDLETASKкоторый описан там как:

#define CLONE_IDLETASK 0x00001000 /* kernel-only flag */

После более глубокого изучения я обнаружил, что, хотя этот флаг не охватывается, man cloneон фактически используется ядром во время процесса загрузки для создания незанятых процессов (каждый из которых должен иметь PID 0) для каждого процессора на машине. то есть машина с 8 процессорами будет иметь как минимум 7 (см. вопрос ниже), такие процессы «работают» (обратите внимание на кавычки).

Теперь это приводит меня к вопросу о том, что на самом деле делает этот «простой» процесс. Я предполагаю, что он выполняет операцию NOP непрерывно до тех пор, пока не истечет его временной интервал, и ядро ​​не назначит реальный процесс для повторного запуска или назначения незанятого процесса (если ЦП не используется). Тем не менее, это полное предположение. Так:

  1. На машине с, скажем, 8 процессорами будут созданы 7 таких бездействующих процессов? (и один процессор будет удерживаться самим ядром, пока не будет выполняться пользовательская область?)

  2. Действительно ли простой процесс представляет собой просто бесконечный поток операций NOP? (или цикл, который делает то же самое).

  3. uptimeРассчитывается ли использование ЦП (скажем ) просто по тому, как долго неактивный процесс был на ЦП и как долго его не было в течение определенного периода времени?


PS Вполне вероятно, что большая часть этого вопроса связана с тем, что я не до конца понимаю, как работает процессор. то есть я понимаю сборку, временные рамки и прерывания, но я не знаю, как, например, процессор может использовать больше или меньше энергии в зависимости от того, что он выполняет. Я был бы признателен, если бы кто-то тоже смог меня просветить.

grochmal
источник
17
Мне пришлось сопротивляться искушению просто написать «Ничего вообще», когда я увидел название.
Vality
4
Большинство современных процессоров будут динамически снижать тактовую частоту и энергопотребление в режиме ожидания или при низкой нагрузке ( динамическое масштабирование частоты , например, SpeedStep для процессоров Intel). Если вы разгоняете процессор, это обычно отключает это поведение, заставляя процессор поддерживать максимальную тактовую частоту даже в режиме ожидания.
Nat
2
См. Также «Состояния питания ACPI»: существует несколько способов, которыми процессор может прекратить выполнение инструкций, но все еще быть активным.
pjc50

Ответы:

85

Неиспользуемая задача используется для учета процессов, а также для снижения энергопотребления. В Linux одна незанятая задача создается для каждого процессора и привязывается к этому процессору; всякий раз, когда на этом процессоре не выполняется никакой другой процесс, задача ожидания назначается. Время, проведенное в неактивных задачах, отображается как «простое» в таких инструментах, как top. (Время работы рассчитывается по-разному.)

Похоже, что в Unix всегда был какой-то цикл ожидания (но не обязательно в режиме реального времени, см. Ответ Жиля ), и даже в V1 он использовал WAITинструкцию, которая останавливала процессор до тех пор, пока не произошло прерывание (оно означало «ждать прерывание»). Некоторые другие операционные системы использовали циклы занятости, в частности DOS, OS / 2 и ранние версии Windows. В течение достаточно долгого времени процессоры использовали такую ​​инструкцию «ожидания», чтобы снизить потребление энергии и выработку тепла. Вы можете увидеть различные реализации пустых задач, например, в arch/x86/kernel/process.cядре Linux: базовая просто вызываетHLT, который останавливает процессор до тех пор, пока не произойдет прерывание (и включает режим энергосбережения C1), другие реализации обрабатывают различные ошибки или неэффективность ( например, использование MWAITвместо HLTнекоторых ЦП).

Все это полностью отделено от неактивных состояний в процессах, когда они ожидают события (ввод-вывод и т. Д.).

Стивен Китт
источник
3
Хех, я вижу это сейчас, спасибо. play_dead()это очень хорошее мнемоническое имя для выполнения HALT. Не было бы риска отправить HALT на каждый процессор и, следовательно, зависнуть? (то есть достижение этой ситуации, остановка каждого процессора, будет ошибкой в ​​ядре?)
grochmal
30
Процессор выходит из HALT через прерывание.
Йохан Мирен
1
@ JohanMyréen - Круто, это имеет смысл. В таком случае даже прерывание IRQ от устройства ввода разбудит его. Благодарю.
grochmal
15
Или, что более надежно, таймер прерывается ... (Tickless - это еще один котелок с рыбой.)
Стивен Китт,
3
@EJP действительно, это довольно распространенная инструкция, хотя она имеет разные имена в разных архитектурах.
user253751
50

В проекте учебника планировщика процессов, если у планировщика нет какого-либо процесса для планирования (т. Е. Если все процессы заблокированы, ожидая ввода), тогда планировщик ожидает прерывания процессора. Прерывание может указывать ввод от периферийного устройства (действия пользователя, сетевой пакет, завершенное чтение с диска и т. Д.) Или может быть прерыванием таймера, которое запускает таймер в процессе.

Планировщик Linux не имеет специального кода для ничего не делающего дела. Вместо этого он кодирует случай «ничего не делать» как особый процесс, бездействующий процесс. Процесс бездействия назначается только в том случае, если не запланирован ни один другой процесс (он фактически имеет бесконечно низкий приоритет). Процесс бездействия фактически является частью ядра: это поток ядра, то есть поток, который выполняет код в ядре, а не код в процессе. (Точнее, есть один такой поток для каждого ЦП.) Когда запускается незанятый процесс, он выполняет операцию ожидания прерывания.

Как работает ожидание прерывания, зависит от возможностей процессора. С самым простым дизайном процессора, это просто занятый цикл -

nothing:
    goto nothing

Процессор всегда выполняет инструкцию ветвления, которая ничего не делает. Большинство современных ОС не делают этого, если они не работают на процессоре, где нет ничего лучше, а большинство процессоров имеют что-то лучшее. Вместо того, чтобы тратить энергию, ничего не делая, кроме обогрева комнаты, в идеале процессор должен быть выключен. Таким образом, ядро ​​запускает код, который инструктирует процессор выключать себя или, по крайней мере, выключать большую часть процессора. Должна быть хотя бы одна маленькая деталь, которая остается включенной, контроллер прерываний. Когда периферийное устройство запускает прерывание, контроллер прерываний отправляет сигнал активизации на основной (часть) процессора.

На практике современные процессоры, такие как Intel / AMD и ARM, имеют много сложных настроек управления питанием. ОС может оценить, как долго процессор будет оставаться в режиме ожидания, и будет выбирать различные режимы с низким энергопотреблением в зависимости от этого. Режимы предлагают различные компромиссы между энергопотреблением в режиме ожидания и временем, необходимым для входа и выхода из режима ожидания. На некоторых процессорах ОС также может снизить тактовую частоту процессора, когда обнаружит, что процессы не занимают много процессорного времени.

Жиль "ТАК - перестань быть злым"
источник
5
Обратите внимание, что даже самые базовые встроенные процессоры, такие как микроконтроллеры на базе AVR, имеют инструкцию WFI (Wait For Interrupt), хотя эта инструкция может быть эквивалентна NOP в зависимости от конкретной модели.
Йонас Шефер
@JonasWielicki Я подумал, что вы обычно просто зацикливаетесь, если вам нечего делать, или вы можете перейти в состояние с низким энергопотреблением и ждать, пока прерывание выбьет вас из этого состояния (состояния с низким энергопотреблением, как правило, требуют большего » металл "перебивает".
Ник Т
1
@JonasWielicki Архитектуры, разработанные для встраиваемых систем, заботятся об управлении питанием, поэтому здесь важна WFI. Многие старые архитектуры не имеют такой вещи. Оригинальная архитектура 8086 не сделала, AFAIR. У 68к есть WFI? Это стандартная функция в MIPS? Мое знакомство с низкоуровневым программированием в основном связано с ARM, где низкое энергопотребление само собой разумеющееся, а WFI - это только верхушка айсберга управления питанием.
Жиль "ТАК ... перестать быть злым"
1
У @Gilles 8086 была инструкция по остановке. См. En.m.wikipedia.org/wiki/HLT_(x86_instruction) Инструкция включала функциональность энергосбережения только начиная с 80486 DX4. Оглядываясь назад в историю, HLT был уже в 8080 году и производными (например, Z80).
Пабук
1
@pabouk HLTмог отключить SL варианты 386 и 486 до выхода DX4 (статья в Википедии неверна).
Стивен Китт
0

Нет, неработающая задача не тратит циклы ЦП. Планировщик просто не выбирает незанятый процесс для выполнения. Неактивный процесс ожидает какого-то события, чтобы оно могло продолжаться. Например, он может ожидать ввода в read()системном вызове.

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

Йохан Мирен
источник
3
Хммм ... Я не думаю, что это тот самый простой процесс, который создается CLONE_IDLETASK. Если бы это было так, его вообще не нужно было бы создавать, т. Е. Если бы планировщик игнорировал незанятые процессы ядра на процессорах, ему не нужно было бы создавать для них какие-либо процессы во время загрузки. (DW не мой, хотя :))
grochmal
Небольшой поиск в Google показывает, что CLONE_IDLETASK является внутренним флагом ядра, который был введен в версии ядра 2.5.14 в 2002 году, а затем удален в 2004 году.
Johan Myréen
«ЭН» простаивает процесс , но не « » простаивает процесс.
user253751