что такое системный таймер на материнской плате
Системный таймер в Windows: большое изменение
Поведение планировщика Windows значительно изменилось в Windows 10 2004 без каких-либо предупреждений и изменения документации. Вероятно, это поломает несколько приложений. Такое происходит не первый раз, но эта перемена посерьёзнее.
Если вкратце, то вызовы timeBeginPeriod из одного процесса теперь влияют на другие процессы меньше, чем раньше, хотя эффект ещё присутствует.
Думаю, что новое поведение — это по сути улучшение, но оно странное, и заслуживает того, чтобы быть задокументированным. Честно предупреждаю — у меня только результаты собственных экспериментов, поэтому могу только догадываться о целях и каких-то побочных эффектах этого изменения. Если какие-либо из моих выводов неверны, пожалуйста, дайте знать.
Прерывания таймера и смысл их существования
Во-первых, немного контекста о дизайне операционных систем. Желательно, чтобы программа могла засыпать, а позже — просыпаться. На самом деле это не следует делать очень часто — потоки обычно ждут событий, а не таймеров, — но иногда необходимо. Итак, в Windows есть функция Sleep — передайте ей желаемую продолжительность сна в миллисекундах, и она разбудит процесс:
Стоит подумать о том, как это реализуется. В идеале при вызове Sleep(1) процессор переходит в спящий режим. Но как операционная система разбудит поток, если процессор спит? Ответ — аппаратные прерывания. ОС программирует микросхему — аппаратный таймер, который затем запускает прерывание, которое пробуждает процессор, и ОС затем запускает ваш поток.
Функции WaitForSingleObject и WaitForMultipleObjects также имеют значения таймаута, и эти таймауты реализуются с использованием того же механизма.
Если много потоков ждут таймеров, то ОС может запрограммировать аппаратный таймер на индивидуальное время для каждого потока, но это обычно приводит к тому, что потоки просыпаются в случайное время, а процессор так нормально и не засыпает. Энергоэффективность CPU сильно зависит от времени его сна (нормальное время от 8 мс), и случайные пробуждения тому не способствуют. Если несколько потоков синхронизируют или объединяют свои ожидания таймера, то система становится более энергоэффективной.
Существует множество способов объединения пробуждений, но основной механизм в Windows — глобальное прерывание таймера, тикающего с постоянной скоростью. Когда поток вызывает Sleep(n), то ОС запланирует запуск потока сразу после первого прерывания таймера. Это означает, что поток может в конечном итоге проснуться немного позже, но Windows — это не ОС реального времени, она вообще не гарантирует определённое время пробуждения (в это время ядра процессора могут быть заняты), поэтому вполне нормально проснуться чуть позже.
Интервал между прерываниями таймера зависит от версии Windows и железа, но на всех моих машинах он по умолчанию составлял 15,625 мс (1000 мс/64). Это означает, что если вызвать Sleep(1) в какое-то случайное время, то процесс будет разбужен где-то между 1,0 мс и 16,625 мс в будущем, когда сработает следующее прерывание глобального таймера (или через одно, если это сработало слишком рано).
Короче говоря, природа задержек таймера такова, что (если только не используется активное ожидание процессора, а его, пожалуйста, не используйте) ОС может пробуждать потоки только в определённое время с помощью прерываний таймера, а Windows использует регулярные прерывания.
Некоторым программам не подходит такой большой разброс в задержках ожидания (WPF, SQL Server, Quartz, PowerDirector, Chrome, Go Runtime, многие игры и т. д.). К счастью, они могут решить проблему с помощью функции timeBeginPeriod, которая позволяет программе запросить меньший интервал. Есть также функция NtSetTimerResolution, которая позволяет устанавливать интервал меньше миллисекунды, но она редко используется и никогда не требуется, поэтому не буду больше её упоминать.
Десятилетия безумия
Вот сумасшедшая вещь: timeBeginPeriod может вызвать любая программа, и она изменяет интервал прерывания таймера, при этом прерывание таймера — это глобальный ресурс.
Представим, что процесс А находится в цикле с вызовом Sleep(1). Это неправильно, но это так, и по умолчанию он просыпается каждые 15,625 мс, или 64 раза в секунду. Затем появляется процесс B и вызывает timeBeginPeriod(2). Это заставляет таймер срабатывать чаще, и внезапно процесс А просыпается 500 раз в секунду вместо 64-х раз в секунду. Это безумие! Но именно так всегда работала Windows.
В этот момент, если бы появился процесс C и вызвал timeBeginPeriod(4), это ничего бы не изменило — процесс A продолжал бы просыпаться 500 раз в секунду. В такой ситуации правила устанавливает не последний вызов, а вызов с минимальным интервалом.
Таким образом, вызов timeBeginPeriod от любой работающей программы может установить глобальный интервал прерывания таймера. Если эта программа завершает работу или вызывает timeEndPeriod, то вступает в силу новый минимум. Если одна программа вызывает timeBeginPeriod(1), то теперь это интервал прерывания таймера для всей системы. Если одна программа вызывает timeBeginPeriod(1), а другая timeBeginPeriod(4), то всеобщим законом становится интервал прерывания таймера в одну миллисекунду.
Это имеет значение, потому что высокая частота прерываний таймера — и связанная с ней высокая частота планирования потоков — может впустую расходовать значительную мощность CPU, как обсуждалось здесь.
Одним из приложений, которому необходимо планирование на основе таймера, является веб-браузер. В стандарте JavaScript есть функция setTimeout, которая просит браузер вызвать функцию JavaScript через несколько миллисекунд. Для реализации этой и других функций Chromium использует таймеры (в основном WaitForSingleObject с таймаутами, а не Sleep). Это часто требует повышенной частоты прерываний таймера. Чтобы это не слишком сказывалось на времени автономной работы, Chromium недавно модифицировали таким образом, чтобы при работе от батареи частота прерываний таймера не превышала 125 Гц (интервал 8 мс).
timeGetTime
Функция timeGetTime (не путать с GetTickCount) возвращает текущее время, обновлённое прерыванием таймера. Процессоры исторически не очень хороши в ведении точного времени (их часы специально колеблются, чтобы не служить FM-передатчиками, и по другим причинам), поэтому для поддержания точного времени CPU часто полагаются на отдельные генераторы тактовых импульсов. Чтение с этих чипов стоит дорого, поэтому Windows поддерживает 64-битный счётчик времени в миллисекундах, обновляемый прерыванием таймера. Этот таймер хранится в общей памяти, поэтому любой процесс может дёшево считывать оттуда текущее время, не обращаясь к генератору тактовых импульсов. timeGetTime вызывает ReadInterruptTick, который по сути просто считывает этот 64-битный счётчик. Все просто!
Поскольку счётчик обновляется прерыванием таймера, мы можем его отследить и найти частоту прерывания таймера.
Новая недокументированная реальность
С выпуском Windows 10 2004 (апрель 2020 года) некоторые из этих механизмов слегка изменились, но очень запутанным образом. Сначала появились сообщения, что timeBeginPeriod больше не работает. На самом деле всё оказалось куда сложнее.
Первые эксперименты дали смешанные результаты. Когда я запустил программу с вызовом timeBeginPeriod(2), то clockres показал интервал таймера 2,0 мс, но отдельная тестовая программа с циклом Sleep(1) просыпалась около 64 раз в секунду вместо 500 раз, как в предыдущих версиях Windows.
Научный эксперимент
Тогда я написал пару программ для изучения поведения системы. Одна программа (change_interval.cpp) просто сидит в цикле, вызывая timeBeginPeriod с интервалами от 1 до 15 мс. Она удерживает каждый интервал в течение четырёх секунд, а затем переходит к следующему, и так по кругу. Пятнадцать строк кода. Легко.
Другая программа (measure_interval.cpp) запускает несколько тестов для проверки, как её поведение изменяется при изменении change_interval.cpp. Программа отслеживает три параметра.
Это означает, что timeBeginPeriod по-прежнему устанавливает интервал глобального таймера во всех версиях Windows. Из результатов timeGetTime() можно сказать, что прерывание срабатывает с такой скоростью по крайней мере на одном ядре процессора, и время обновляется. Обратите также внимание, что 2.0 в первой строке для 1909 года тоже было 2.0 в Windows XP, затем 1.0 в Windows 7/8, а затем вроде опять вернулось к 2.0?
Однако поведение планировщика резко меняется в Windows 10 2004. Ранее задержка для Sleep(1) в любом процессе просто равнялась интервалу прерывания таймера, за исключением timeBeginPeriod(1), давая такой график:
В Windows 10 2004 соотношение между timeBeginPeriod и задержкой сна в другом процессе (который не вызывал timeBeginPeriod) выглядит странно:
Точная форма левой части графика неясна, но она определённо уходит в противоположную сторону от предыдущего!
Последствия
Как было указано в обсуждении reddit и hacker-news, вероятно, левая половина графика представляет собой попытку максимально точно имитировать «нормальную» задержку, учитывая доступную точность глобального прерывания таймера. То есть с интервалом прерывания 6 миллисекунд задержка происходит примерно на 12 мс (два цикла), а с интервалом прерывания 7 миллисекунд — примерно на 14 мс (два цикла). Однако измерение фактических задержек показывает, что реальность ещё более запутанна. При прерывании таймера, установленном на 7 мс, задержка Sleep(1) в 14 мс даже не самый распространённый результат:
Некоторые читатели могут обвинить случайный шум в системе, но когда частота прерывания таймера 9 мс и выше, шум равен нулю, так что это не может быть объяснением. Попробуйте сами запустить обновлённый код. Особенно противоречивыми кажутся интервалы прерывания таймера от 4 мс до 8 мс. Вероятно, измерения интервалов следует выполнять с помощью QueryPerformanceCounter, поскольку на текущий код беспорядочно влияют изменение правил планирования и изменение точности таймера.
Всё это очень странно, и я не понимаю ни логики, ни реализации. Может, это и ошибка, но я в этом сомневаюсь. Думаю, что за этим стоит сложная логика обратной совместимости. Но самый эффективный способ избежать проблем совместимости — это документировать изменения, желательно заранее, а здесь правки сделаны без какого-либо уведомления.
Это не повлияет на большинство программ. Если процесс хочет более быстрое прерывание таймера, то он сам должен вызвать timeBeginPeriod. Тем не менее, могут возникнуть следующие проблемы:
Расшифровка звуковых сигналов AMI и AWARD BIOS
BIOS (Basic Input/Output System – базовая система ввода-вывода).
Программа системного уровня, предназначенная для первоначального запуска компьютера, настройки оборудования и обеспечения функций ввода/вывода. ВIOS записывается в микросхему постоянной памяти, которая расположена на системной плате.
В персональных и портативных компьютерах система BIOS производит запуск компьютера и процедуру самотестирования (Power-On Self Test – POST). Программа, расположенная в микросхеме BIOS, загружается первой после включения компьютера.
Программа определяет и проверяет установленное оборудование, настраивает устройства и готовит их к работе. При самотестировании, возможно, будет обнаружена неисправность оборудования, тогда процедура POST будет остановлена с выводом соответствующего сообщения или звукового сигнала. Если же все проверки прошли успешно, самотестирование завершается вызовом встроенной подпрограммы для загрузки операционной системы. Ну а если же программой будет выявлена серьезная ошибка, работа системы будет остановлена с выдачей звуковых сигналов, которые укажут на возникшую неисправность. Поэтому представляем вам звуковые сигналы ведущих производителей BIOS, такие как: AMI BIOS, Award BIOS, Phoenix BIOS.
AMI BIOS
• 1 короткий сигнал — проблем не обнаружено;
• 2 коротких — неисправность оперативной памяти;
• 3 коротких — неисправность оперативной памяти;
• 4 коротких — неисправность материнской платы;
• 5 коротких — неисправность центрального процессора;
• 6 коротких — проблема с клавиатурой;
• 7 коротких — неисправность материнской платы;
• 8 коротких — проблема с памятью видеокарты;
• 9 коротких — неисправен BIOS материнской платы;
• 10 коротких — ошибки в микросхеме CMOS материнской платы или села питающая ее батарейка;
• 11 коротких — ошибка кэша материнской платы;
• 1 длинный + 1 короткий — неисправен блок питания;
• 1 длинный + 2 коротких — проблема с видеокартой или разъемами оперативной памяти;
• 1 длинный + 3 коротких — неисправна видеокарта или к разъемам материнской платы подключены неподдерживаемые модули ОЗУ;
• 1 длинный + 4 коротких — нет видеокарты;
• 1 длинный + 8 коротких — неисправна видеокарта или к ней не подключен монитор;
• 3 длинных — неисправен один или несколько модулей оперативной памяти;
• 5 коротких + 1 длинный — отсутствует оперативная память или модули ОЗУ установлены не правильно;
• Постоянный звуковой сигнал — компьютер перегрелся, возникли проблемы с оперативной памятью или блоком питания.
Phoenix BIOS
В BIOS этого типа используются серии коротких звуковых сигналов с паузами между ними (цифры ниже обозначают количество сигналов, а тире — паузы):
• 1-1-2 — процессор вышел из строя;
• 1-1-3 — ошибка записи / чтения в / из CMOS-памяти или разрядилась питающая ее батарейка;
• 1-1-4 — ошибка в BIOS материнской платы;
• 1-2-1 — проблема с материнской платой;
• 1-2-2 — проблема с контроллером DMA (контроллером прямого доступа к оперативной памяти);
• 1-2-3 — ошибка контроллера DMA;
• 1-3-1 — проблема с оперативной памятью;
• 1-3-3 — неисправность оперативной памяти;
• 1-3-4 — неисправность оперативной памяти;
• 1-4-1 — неисправность материнской платы;
• 1-4-2 — проблемы с оперативной памятью;
• 1-4-3 — ошибка инициализации системного таймера;
• 1-4-4 — проблема с одним из портов ввода-вывода;
• 2-1-1 — ошибка чтения / записи из / в оперативную память;
• 2-1-2 — ошибка чтения / записи из / в оперативную память;
• 2-1-3 — ошибка чтения / записи из / в оперативную память;
• 2-1-4 — ошибка чтения / записи из / в оперативную память;
• 2-2-1 — ошибка чтения / записи из / в оперативную память;
• 2-2-2 — ошибка чтения / записи из / в оперативную память;
• 2-2-3 — ошибка чтения / записи из / в оперативную память;
• 2-2-4 — ошибка чтения / записи из / в оперативную память;
• 2-3-1 — ошибка чтения / записи из / в оперативную память;
• 2-3-2 — ошибка чтения / записи из / в оперативную память;
• 2-3-3 — ошибка чтения / записи из / в оперативную память;
• 2-3-4 — ошибка чтения / записи из / в оперативную память;
• 2-4-1 — ошибка чтения / записи из / в оперативную память;
• 2-4-2 — ошибка чтения / записи из / в оперативную память;
• 2-4-3 — ошибка чтения / записи из / в оперативную память;
• 2-4-4 — ошибка чтения / записи из / в оперативную память;
• 3-1-1 — ошибка инициализации канала DMA (канала прямого доступа к оперативной памяти);
• 3-1-2 — ошибка инициализации канала DMA;
• 3-1-4 — ошибка инициализации канала DMA;
• 3-2-4 — проблема с контроллером клавиатуры;
• 3-3-4 — проблема с видеокартой;
• 3-4-1 — неисправен монитор;
• 3-4-2 — проблема с BIOS видеокарты;
• 4-2-1 — ошибка инициализации системного таймера;
• 4-2-3 — проблема с клавиатурой;
• 4-2-4 — проблема с центральным процессором;
• 4-3-1 — ошибка инициализации оперативной памяти;
• 4-3-2 — проблема с системным таймером;
• 4-3-3 — проблема с системным таймером;
• 4-4-1 — неполадка одного из последовательных портов;
• 4-4-2 — неполадка параллельного порта;
• 4-4-3 — проблема с математическим сопроцессором, неполадка центрального процессора;
• Постоянно повторяющиеся сигналы — материнская плата вышла из строя;
• Звук сирены — неисправность видеокарты, необходимо заменить конденсаторы;
• Непрерывный сигнал — система охлаждения центрального процессора вышла из строя.
О чем говорит нам компьютер
При наблюдении одной приведённых неисправностей виде сигналов (кроме одиночного короткого сигнала) обратитесь за помощью к специалистам сервисного центра по ремонту и обслуживанию компьютерной техники! Постарайтесь пресечь, любые попытки самостоятельного ремонта, вмешательство в неисправное оборудование может усугубить проблему.
Последовательность звуковых сигналов | Описание ошибки | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2 коротких | Обнаружены незначительные ошибки. Beep-коды представлены последовательностью звуковых сигналов. Например, 1-1-2 означает 1 звуковой сигнал, пауза, 1 звуковой сигнал, пауза, и 2 звуковых сигнала.
Обозначение звуковых сигналов биос при включении пкВ зависимости от производителя BIOS определенная последовательность сигналов может обозначать наличие разных проблем. Прежде чем приступать к расшифровке конкретной звуковой последовательности необходимо определить производителя BIOS. Сделать это можно, определив модель материнской платы, а затем набрав ее в интернете и перейдя на официальный сайт производителя прочитать в спецификациях. Если же вы не смогли определить производителя bios, то можете просто перебирать варианты решения поочередно от всех трех основных производителей – AMI, AWARD, Phoenix, расшифровка сигналов которых будет приведена в трех отдельных таблицах ниже. Расшифровка звуковых синалов AMI BIOS
Расшифровка звуковых сигналов AWARD BIOS
Расшифровка звуковых сигналов Phoenix BIOS У phoenix звуковые сигналы представлены в виде бипов. Комбинация, записанная в таблице как 1-2-2 будет значить 1 сигнал (бип) пауза, затем 2 сигнала (бипа) пауза и снова 2 сигнала (бипа).
Некоторые рекомендации по устранению проблем.Производитель BIOSУ каждого производителя BIOS, своя последовательность и расшифровка звуковых сигналов. Прежде чем приступать к расшифровке, необходимо узнать производителя. Способ 1Самый простой способ определить фирму – в момент загрузки, обычно указывается производитель и версия BIOS. Способ 2Можно зайти в BIOS во время запуска и найти пункт «System Information» или с помощью программы Everest (Aida) в Windows. В обоих случаях, будет указана вся информация. Сейчас все современные компьютеры выходят с обновленным BIOS под названием UEFI.
|