Почему отключение прерываний отключает вытеснение ядра и как блокировка вращения отключает вытеснение

Я недавно читаю Разработка ядра Linux, и у меня есть несколько вопросов, связанных с отключением вытеснения.

  1. # P2 #
    # P3 #
    # P4 #
    # P5 #
    # P6 #
  2. # P7 # # P8 #
    # P9 #
    # P10 #

person feirainy    schedule 25.12.2013    source источник


Ответы (4)


Я не гуру планировщика, но я хотел бы объяснить, как я это вижу. Вот несколько вещей.

  1. preempt_disable () не отключает IRQ. Он просто увеличивает thread_info->preempt_count переменную.
  2. Отключение прерываний также отключает приоритетное прерывание, потому что после этого планировщик не работает - но только на однопроцессорной машине. На SMP этого недостаточно, потому что, когда вы закрываете прерывания на одном процессоре, другой / другие по-прежнему делают / делают что-то асинхронно.
  3. Большой замок (означает закрытие всех прерываний на всех процессорах) резко замедляет работу системы - вот почему она больше не используется. Это также причина, по которой preempt_disable () не закрывает IRQ.

Вы можете увидеть, что такое preempt_disable (). Попробуйте следующее: 1. Получите спин-блокировку. 2. Расписание звонков ()

В dmesg вы увидите что-то вроде «ОШИБКА: планирование при атомарном режиме». Это происходит, когда планировщик обнаруживает, что ваш процесс находится в атомарном (не вытесняющем) контексте, но планирует сам.

Удачи.

person Sebastian Mountaniol    schedule 26.12.2013
comment
Спасибо за подробный ответ. Но я до сих пор не понимаю, почему планировщик не работает после отключения прерываний на однопроцессорной машине. - person feirainy; 27.12.2013
comment
Без прерываний - без часов. Нет часов - нет таймеров. - person Sebastian Mountaniol; 27.12.2013
comment
Каков будет эффект, если я отключу только приоритетное прерывание (не отключая прерывания) и в то же время в системе произойдет прерывание, и что произойдет после отключения прерывания? и в этом случае переменная preempt_count будет более эффективной. (изучение обработки прерывания в руке) - person enfinet; 24.05.2016
comment
@Sebastian Mountaniol: The Big Lock (означает - закрытие всех прерываний на всех процессорах) Вы можете это объяснить? Большая блокировка - это фактически блокировка, хотя и глобальная для всех LWP. Но это не означает отключение прерываний. - person ultimate cause; 04.10.2017

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

1 - Использование local_irq_save ()

2 - Использование spin_lock_irqsave ()

3 - Вручную disable_irq () для всех IRQ в / proc / interrupts

Во всех трех случаях я все еще мог использовать hrtimer для измерения времени, даже если IRQ были отключены (и задача, которую я отслеживал, также была прервана).

Мне это кажется странным ... Я лично ожидал того, на что указал Себастьян Маунтаниол -> Никаких прерываний - никаких часов. Нет часов - нет таймеров ...

Ядро Linux 2.6.32 на одном ядре, одном процессоре ... Может у кого-нибудь есть лучшее объяснение?

person fakr00n    schedule 11.02.2014
comment
Я думал, что некоторые таймеры ядра Linux используют уловку последнего прерывания таймера плюс таймер цикла процессора. Так вы получите точное время до переполнения счетчика циклов. - person Zan Lynx; 25.02.2014

  1. preempt_disable() не отключает прерывания. Однако он увеличивает счетчик вытеснения. Допустим, вы вызываете preempt_disable() n раз в пути кода, приоритетное прерывание будет разрешено только на n-м preempt_enable().
  2. отключение прерываний для предотвращения вытеснения: небезопасный способ. Это, несомненно, отключит обычное приоритетное прерывание ядра, потому что scheduler_tick() не будет вызываться при системном тике (не вызывается обработчик прерывания). Однако, если программа запускает функцию расписания, приоритетное обслуживание произойдет, если preempt_disable() не был вызван.
  3. В Linux raw_spin_lock() не отключает локальные прерывания, которые могут привести к тупиковой ситуации. Например, если вызывается обработчик прерывания, который пытается заблокировать уже удерживаемую блокировку спина, он не сможет этого сделать, если сам процесс не освободит его, что невозможно, поскольку не произойдет возврата из прерывания. Так что лучше использовать raw_spin_lock_irq(), который отключает прерывания.
person Lucifer Poltergeist    schedule 20.07.2020

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

Например, с отключенными прерываниями cond_resched () все равно будет вызывать приоритетное прерывание, но не будет, если прерывание было явно отключено.

Вот почему, что касается вашего второго вопроса, спин-блокировки не используют отключение прерывания для отключения вытеснения. Они явно вызывают preempt_disable (), которая увеличивает preempt_count и отключает все возможные способы вытеснения, за исключением явных вызовов schedule ().

person Matviy Kotoniy    schedule 16.09.2020