Содержание


Инструменты программирования в ядре: Часть 66. Служба времени: базовые понятия

Comments

Сложилось определённое мнение, что динамическое управление памятью, рассмотренное в предыдущих статьях, является сложной темой. На самом деле это не так, и по настоящему сложной и неисчерпаемой темой (в любой операционной системе!) является служба времени. Ещё одной особенностью подсистемы времени, которой мы ещё неоднократно воспользуемся, является то, что нюансы поведения службы времени, как ни одной другой службы, можно с одинаковым успехом анализировать как в пространстве ядра, так и в пользовательском пространстве. В обоих случаях эти нюансы проявляются одинаково, а мелкие различия позволяют лучше понять наблюдаемые явления. Поэтому многие вопросы, относящиеся ко времени, проще изучить с помощью кода пользовательского адресного пространства, а не ядра, чем мы и займёмся в этой и последующих статьях.

Информация о времени в ядре

Во всех функциях времени, основным принципом остаётся положение, сформулированное расширением реального времени POSIX 1003b: временные интервалы никогда не могут быть короче, чем затребованные, но могут быть сколь угодно больше затребованных (например, выдерживающий паузу поток может быть вытеснен более приоритетным на неограниченно длительное время).

Сложность подсистемы времени усугубляется тем, что для повышения точности или функциональности API времени, разработчики могут использовать несколько разнородных и не синхронизированных источников временных меток (из числа тех, которые позволяет та или иная конкретная аппаратная платформа). Точный набор таких дополнительных возможностей определяется аппаратными возможностями самой платформы, более того, на одной и той же архитектурной платформе, например, x86 набор и возможности временных устройств обновляются с развитием и изменяются каждые 2-3 года, а, соответственно, изменяется всё поведение подсистемы времени. Но какие бы не были платформенные или архитектурные различия, следует отчётливо разделять обязательный в любых условиях системный таймер и дополнительные источники информации времени в системе. Всё относящееся к системному таймеру является основой функционирования Linux и не зависит от платформы, все остальные альтернативные возможности зависят от своих реализаций на конкретной платформе.

Ядро следит за течением времени с помощью прерываний системного таймера. Прерывания таймера генерируются аппаратно через постоянные интервалы системным таймером. Этот интервал программируется во время начальной загрузки Linux записью соответствующего коэффициента в аппаратный счётчик-делитель. Делается эта запись в соответствии с одной из самых фундаментальных констант ядра — константы периода компиляции (определённой директивой #defined) с именем HZ (tick rate). Значение этой константы является архитектурно-зависимой величиной и определено в файле <linux/param.h>. Значения по умолчанию в исходных текстах ядра имеют диапазон от 50 до 1200 тиков в секунду на различном реальном оборудовании, снижаясь до 24 в программных эмуляторах (виртуальных машинах). Но для большинства платформ для ядра 2.6 выбраны значения HZ=1000, что соответствует периоду следования системных тиков в 1 миллисекунду — это достаточно мало для обеспечения хорошей динамики системы, но очень много в сравнении с временем выполнения единичной команды процессора. По прерыванию системного таймера происходят все важнейшие события в системе:

  • обновление значения времени работы системы (uptime), абсолютного времени (time of day);
  • проверка, не израсходовал ли текущий процесс свой квант времени, и если израсходовал, то происходит планирование выполнения нового процесса;
  • для SMP-систем проверяется балансировка очередей выполнения планировщика, и если они не сбалансированы, то производится их балансировка;
  • выполнение обработчиков всех созданных динамических таймеров, для которых истек период времени;
  • обновление статистики по использованию процессорного времени и других ресурсов.

Снижение периода следования системных тиков обеспечивает лучшие динамические характеристики системы (например, в системе реального времени QNX период следования системных тиков может быть сокращён до 10 микросекунд), но при снижении этого значения ниже определённого предела начинает существенно снижаться общая производительность операционной системы, так как возрастают непроизводительные расходы на обслуживание частых прерываний.

Источник прерываний системного таймера

Источник прерываний системного таймера (определяющий последовательность тиков частоты HZ, и подсчитываемых в счётчике jiffies) — аппаратная микросхема системного таймера. В архитектуре x86 в этом качестве используется микросхема по типу Intel 82C54, работающая от отдельного кварца стандартизованной частоты 1.1931816Мгц; далее эта частота делится на целочисленный делитель, записываемый в регистры 82C54.

$ cat /proc/interrupts
        CPU0
  0:    5737418          XT-PIC  timer
...
  8:          1          XT-PIC  rtc

При выбранном значении делителя 1193 обеспечивается частота последовательности прерываний таймера максимально близкая к выбранному в заголовочном файле <linux/param.h> значению HZ— 1000.152hz, что соответствует периоду (ticksize) 999847нс (рассогласование с 1мс составляет -0,0153%).

Примечание: ближайшее соседнее значение делителя 1194 даёт частоту и период 999.314hz и 1000680нс (рассогласование с 1мс составляет +0,068%), соответственно, но всегда используется значение периода с недостатком, так как в противном случае задержка, величина которой определена, например, как:

  struct timespec ts = { 0 /* секунды */, 1000500 /* наносекунды */ };

— могла бы (при некоторых прогонах) завершиться на первом же тике, что противоречит требованиям POSIX 1003b о том, что временной интервал может быть больше, но ни в коем случае не меньше указанного!

Тот же принцип формирования периода системных тиков соблюдается и на любой другой аппаратной платформе, на которой выполняется Linux: целочисленный делитель счётчика, задающий максимальное приближенное аппаратное значения частоты к выбранному значению константы HZ с избытком (то есть период системного таймера с недостатком к значению 1/HZ). Эта информация нам понадобится впоследствии для анализа результатов тестов.

Дополнительные источники информации о времени

Кроме системного таймера, в системе может быть (в зависимости от процессорной архитектуры и уровня её развития) ещё несколько источников событий для временной шкалы: часы реального времени (RTC), таймеры контроллеров прерываний APIC, специальные счётчики процессорных тактов и другие. Эти источники временных шкал могут использоваться для уточнения значений интервалов системного таймера. С развитием и расширением возможностей любой аппаратной платформы, разработчики ядра стараются подхватить и использовать любые новые появившиеся аппаратные механизмы. Связано это желание с тем, что, как уже было сказано, стандартный период системного таймера превышает (на 2 порядка и более) время выполнения единичной команды процессора. Поэтому в масштабе времён выполнения команд период системного таймера получается слишком большой величиной, и интервальные значения, измеренные в шкале системных тиков, пытаются уточнить разными способами с привлечением дополнительных источников. Это приводит к тому, что близкие версии ядра на однотипном оборудовании разных лет изготовления могут использовать существенно различающиеся точности для оценивания временных интервалов, как и показано ниже.

Так для 2-х ядерного ноутбука уровня 2007г. мы получим:

$ cat /proc/interrupts
         CPU0             CPU1
   0:    3088755          0   IO-APIC-edge      timer
...
   8:          1          0   IO-APIC-edge      rtc0
...
 LOC:    2189937    2599255   Local timer interrupts
...
 RES:    1364242    1943410   Rescheduling interrupts
$ uname -r
2.6.32.9-70.fc12.i686.PAE

А для более современного 4-х ядерного процессора образца 2011г. уже:

$ cat /proc/interrupts
             CPU0       CPU1       CPU2       CPU3
   0:        127          0          0          0   IO-APIC-edge      timer
...
   8:          0          0          0          0   IO-APIC-edge      rtc0
...
 LOC:  460580288  309522125 2269395963  161407978   Local timer interrupts
...
 RES:     919591     983178     315144     626188   Rescheduling interrupts
$ uname -r
2.6.35.11-83.fc14.i686

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

Три класса задач во временной области.

Существуют три класса задач, решаемых во временной области, это:

  1. измерение временных интервалов;
  2. выдержка пауз во времени;
  3. выполнение действий, отложенных во времени.

В отношении задач каждого класса существуют свои ограничения, возможности использования дополнительных источников уточнения информации о времени и, как следствие, предельное временное разрешение, которое может быть достигнуто в каждом классе задач. Например, отложенные во времени действия (действия, планируемые по таймерам), чаще всего, привязываются к шкале системных тиков (тем же точкам во времени, где происходит и диспетчирование выполняемых потоков системой) — разрешение такой шкалы соответствует системным тикам, и это миллисекундный диапазон. Напротив, пассивное измерение временного интервала между двумя точками отсчёта в коде программы, вполне может основываться на таких простейших механизмах, как считанные значения счётчика тактовой частоты процессора, а это может обеспечивать разрешение шкалы времени в наносекундном диапазоне. Разница в разрешении между двумя рассмотренными случаями получится около 6 порядков!

Заключение

Служба времени является основой функционирования любой операционной системы, хотя её значимость для системы и не всегда явно видна на уровне пользователя. В этой части были классифицированы базовые понятия службы времени и поддерживающие её механизмы. Далее это позволит гибко использовать возможности службы времени в своём программном коде.


Ресурсы для скачивания


Похожие темы


Комментарии

Войдите или зарегистрируйтесь для того чтобы оставлять комментарии или подписаться на них.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Linux, Open source
ArticleID=937745
ArticleTitle=Инструменты программирования в ядре: Часть 66. Служба времени: базовые понятия
publish-date=07182013