Почему процессы лишены CPU слишком долго, пока заняты циклом в ядре Linux?

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

Я определил цикл занятости в моем модуле ядра Linux. Из-за этого другие процессы (например, sshd) не получают время процессора в течение длительного промежутка времени (например, 20 секунд). Это понятно, поскольку моя машина имеет только один процессор, а цикл занятости не дает возможности планировать другие процессы.

просто для эксперимента я добавил schedule () после каждой итерации в занятая петля. Несмотря на то, что это будет держать CPU занятым, он все равно должен позволить другим процессам работать, поскольку я вызываю schedule(). Но, кажется, этого не происходит. Мои процессы пользовательского уровня все еще висят в течение длительного промежутка времени (20 секунд).

в этом случае поток ядра получил хорошее значение -5, а потоки пользовательского уровня получили хорошее значение 0. Даже с низким приоритетом потока пользовательского уровня я думаю, что 20 секунд слишком долго, чтобы не получить процессор.

может кто-нибудь объяснить, почему это могло случиться?

примечание: Я знаю, как полностью удалить занятый цикл. Но я хочу понять поведение kernel здесь. Версия ядра 2.6.18 и упреждение ядра отключается.

1 ответов


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

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

в качестве эксперимента вы можете попробовать вызвать планировщик каждую N-ю итерацию цикла (вам придется поэкспериментировать, чтобы найти хорошее значение N для вашей платформы) и посмотреть, лучше ли ситуация - вызов schedule() слишком часто будет просто тратить много времени процессора в планировщике. Конечно, это всего лишь эксперимент - как вы уже указывали, избегать занятых циклов-правильный вариант в производственном коде, и если вы хотите убедиться, что ваш поток заменен другим, установите его TASK_INTERRUPTIBLE перед вызовом schedule() удалиться из очереди выполнения (как уже упоминалось в комментариях).

обратите внимание, что ваше ядро (2.6.18) использует планировщик O(1), который существовал до Абсолютно Справедливый Планировщик был добавлен в 2.6.23(планировщик O (1) был добавлен в 2.6, чтобы заменить еще более старый o(n) планировщик). CFS не использует очереди запуска и работает по - другому, поэтому вы можете увидеть другое поведение-Я менее знаком с ним, однако, поэтому я не хотел бы точно предсказывать, какие различия вы увидите. Я видел достаточно, чтобы знать ,что "полностью справедливый" - это не тот термин, который я бы использовал для тяжело загруженных систем SMP с большим количество ядер и процессов, но я также признаю, что написание планировщика-очень сложная задача, и это далеко не самое худшее, что я видел, и у меня никогда не было значительных проблем с ним на настольной машине 4-8 core.