Категории
Самые читаемые
onlinekniga.com » Компьютеры и Интернет » Программирование » Разработка ядра Linux - Роберт Лав

Разработка ядра Linux - Роберт Лав

Читать онлайн Разработка ядра Linux - Роберт Лав

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 58 59 60 61 62 63 64 65 66 ... 132
Перейти на страницу:

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

Когда обработчик таймера сработает, создается новый таймер для следующего события и так повторяется постоянно. При таком подходе не требуется периодическое прерывание таймера и нет необходимости в параметре HZ.

Однако при указанном подходе необходимо решить две проблемы. Первая проблема — это как в таком случае реализовать концепцию периодических отметок времени, хотя бы для того, чтобы ядро могло отслеживать относительные интервалы времени. Эту проблему решить не сложно. Вторая проблема — это как избежать накладных затрат, связанных с управлением динамическими таймерами, даже при наличии оптимизации. Данную проблему решить сложнее. Накладные расходы и сложность реализации получаются настолько высокими, что в операционной системе Linux такой подход решили не использовать. Тем не менее так пробовали делать, и результаты получаются интересными. Если интересно, то можно поискать в Интернет-архивах.

Переменная jiffies

Глобальная переменная jiffies содержит количество импульсов системного таймера, которые были получены со времени загрузки системы. При загрузке ядро устанавливает значение этого параметра в нуль и он увеличивается на единицу при каждом прерывании системного таймера. Так как в секунду возникает HZ прерываний системного таймера, то за секунду значение переменной jiffies увеличивается на HZ. Время работы системы (uptime) поэтому равно jiffies/HZ секунд.

Этимология слова jiffy

Происхождение слова jiffy (миг, мгновение) точно неизвестно. Считается, что фразы типа "in a jiffy" (в одно мгновение) появились в Англии в восемнадцатом веке. В быту термин jiffy (миг) означает неопределенный, но очень короткий промежуток времени.

В научных приложениях слово jiffy используется для обозначения различных интервалов времени (обычно порядка 10 ms). В физике это слово иногда используется для указания интервала времени, который требуется свету, чтобы пройти определенное расстояние (обычно, фут, сантиметр, или расстояние, равное размеру нуклона).

В вычислительной технике термин jiffy — это обычно интервал времени между двумя соседними импульсами системного таймера, которые были успешно обработаны. В электричестве jiffy — период переменного тока. В США jiffy — это 1/60 секунды.

В приложении к операционным системам, в частности к Unix, jiffy — это интервал времени между двумя соседними успешно обработанными импульсами системного таймера. Исторически это значение равно 100 ms. Как уже было показано, интервал времени jiffy в операционной системе Linux может иметь разные значения.

Переменная jiffies определена в файле <linux/jiffies.h> следующим образом.

extern unsigned long volatile jiffies;

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

(секунды * HZ)

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

(jiffies / HZ)

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

unsigned long time_stamp = jiffies;    /* сейчас */

unsigned long next_tick = jiffies + 1; /* через один импульс таймера

                                          от текущего момента */

unsigned long later = jiffies + 5*HZ;  /* через пять секунд от текущего

                                          момента */

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

Заметим, что переменная jiffies имеет тип unsigned long и использовать какой-либо другой тип будет неправильным.

Внутреннее представление переменной jiffies

Переменная jiffies исторически всегда представлялась с помощью типа unsigned long и, следовательно, имеет длину 32 бит для 32-разрядных аппаратных платформ и 64 бит для 64-разрядных. В случае 32-разрядного значения переменной jiffies и частоты появления временных отметок 100 раз в секунду, переполнение этой переменной будет происходить примерно каждые 497 дней, что является вполне возможным событием. Увеличение значения параметра HZ до 1000 уменьшает период переполнения до 49.7 дней! В случае 64-разрядного типа переменной jiffies, переполнение этой переменной невозможно за время существования чего-либо при любых возможных значениях параметра HZ для любой аппаратной платформы.

Из соображений производительности и по историческим причинам — в основном, для совместимости с уже существующим кодом ядра — разработчики ядра предпочли оставить тип переменной jiffies — unsigned long. Для решения проблемы пришлось немного подумать и применить возможности компоновщика.

Как уже говорилось, переменная jiffies определяется в следующем виде и имеет тип unsigned long.

extern unsigned long volatile jiffies;

Вторая переменная определяется в файле <linux/jiffies.h> в следующем виде.

extern u64 jiffies_64;

Директивы компоновщика ld(1), которые используются для сборки главного образа ядра (для аппаратной платформы x86 описаны в файле arch/i386/kernel/vmlinux.lds.S), указывают компоновщику, что переменную jiffies необходимо совместить с началом переменной jiffies_64.

jiffies = jiffies_64;

Следовательно, переменная jiffies — это просто 32 младших разряда полной 64-разрядной переменной jiffies_64. Так как в большинстве случаев переменная jiffies используется для измерения промежутков времени, то для большей части кода существенными являются только младшие 32 бит.

В случае применения 64-разрядного значения, переполнение не может возникнуть за время существования чего-либо. В следующем разделе будут рассмотрены проблемы, связанные с переполнением (хотя переполнение счетчика импульсов системного таймера и не желательно, но это вполне нормальное и ожидаемое событие). Код, который используется для управления ходом времени, использует все 64 бит, и это предотвращает возможность переполнения 64-разрядного значения. На рис. 10.1 показана структура переменных jiffies и jiffies_64.

Рис. 10.1. Структура переменных jiffies и jiffies_64

Код, который использует переменную jiffies, просто получает доступ к тридцати двум младшим битам переменной jiffies_64. Функция get_jiffies_64() может быть использована для получения полного 64-разрядного значения[57]. Такая необходимость возникает редко, следовательно большая часть кода просто продолжает считывать младшие 32 разряда непосредственно из переменной jiffies.

На 64-разрядных аппаратных платформах переменные jiffies_64 и jiffies просто совпадают. Код может либо непосредственно считывать значение переменной jiffies, либо использовать функцию get_jiffies_64(), так как оба этих способа позволяют получить аналогичный эффект.

Переполнение переменной jiffies

Переменная jiffies, так же как и любое целое число языка программирования С, после достижения максимально возможного значения переполняется. Для 32-разрядного беззнакового целого числа максимальное значение равно 2³²- 1. Поэтому перед тем как счетчик импульсов системного таймера переполнится, должно прийти 4294967295 импульсов таймера. Если значение счетчика равно этому значению и счетчик увеличивается на 1, то значение счетчика становится равным нулю.

Рассмотрим пример переполнения.

unsigned long timeout = jiffies + HZ/2; /* значение лимита времени

                                           равно 0.5 с */

/* выполним некоторые действия и проверим, не слишком ли это много

   заняло времени ... */

if (timeout < jiffies) {

 /* мы превысили лимит времени — это ошибка ... */

} else {

 /* мы не превысили лимит времени — это хорошо ... */

1 ... 58 59 60 61 62 63 64 65 66 ... 132
Перейти на страницу:
На этой странице вы можете бесплатно читать книгу Разработка ядра Linux - Роберт Лав.
Комментарии