Как пробуждаются спящие нити на самом низком уровне?

Я задавался вопросом об этом в течение очень долгого времени.

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

Мой вопрос, однако, таков: как операционная система проверяет доступные сообщения? Где-то в стеке, я полагаю, должен быть цикл, который постоянно проверяет наличие новых событий. В таком цикле не может быть какой-либо блокировки, потому что если это так, должен быть еще один циклический поток, который «всегда бодрствует», готовый разбудить первый. Тем не менее, я также понимаю, что это не может быть правдой, потому что в противном случае я ожидал бы увидеть 100% по крайней мере одного ядра процессора, используемого постоянно, проверяя снова и снова, снова и снова....

Я подумал, что, возможно, проверяющий поток имеет небольшой сон между каждой итерацией. Это, безусловно, объясняет, почему бездействующая система не использует 100% ЦП. Но потом я вспомнил, как обычно на события реагируют мгновенно. Возьмем, к примеру, движение мыши: курсор постоянно перерисовывается синхронно с физическими движениями.

Возможно, есть что-то фундаментальное в архитектуре ЦП, позволяющее запускать потоки на аппаратном уровне при изменении значения определенных адресов памяти?

У меня иначе нет идей! Может ли кто-нибудь помочь объяснить, что на самом деле происходит?


person DarkOwl    schedule 19.09.2015    source источник
comment
Да есть: аппаратные прерывания. Грубое упрощение: когда нажимается клавиша или перемещается мышь, ОС обрабатывает прерывание и проверяет, есть ли спящие потоки, которые «заблокированы для ввода-вывода» — ожидающие ввода — и затем пробуждает их. Такие спящие потоки вызывают вызов ядра подобно вашему get_message, и если нет доступных данных, поток не будет запланирован для запуска до тех пор, пока данные не будут доступны.   -  person Kenney    schedule 19.09.2015
comment
Спасибо, Кенни. Само утверждение о том, что аппаратное обеспечение задействовано, ответило на мой вопрос. Если кто-то захочет написать это как формальный ответ, я с радостью приму его. Как именно такие аппаратные прерывания влияют на низкоуровневое программное обеспечение, я думаю, гораздо большая банка червей, которую я не осмелюсь открыть здесь!   -  person DarkOwl    schedule 19.09.2015


Ответы (1)


Да есть: аппаратные прерывания.

При нажатии клавиши или перемещении мыши, прибытии сетевого пакета, считывании данных с какого-либо другого устройства или истечении времени таймера ОС получает аппаратное прерывание.

Потоки или приложения, желающие выполнять ввод-вывод, должны вызывать функцию в ОС, которая возвращает запрошенные данные, или приостанавливает вызывающий поток, если данные еще недоступны. Эта приостановка просто означает, что поток не рассматривается для планирования до тех пор, пока не изменится какое-либо условие — в этом случае запрошенные данные должны быть доступны. О таких потоках говорят, что они заблокированы.

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

В этом управляемом прерываниями режиме процессорное время не тратится впустую на «опрос» данных.

person Kenney    schedule 19.09.2015