вторник, 7 декабря 2010 г.

7.2. Определение текущего времени

7.2. Определение текущего времени

Код ядра всегда может получить представление о текущем время, глядя на значение jiffies. Обычно, тот факт, что значение предоставляет только время, прошедшее с последней загрузки, не влияет на драйвер, потому что его жизнь ограничена временем работы системы. Как было показано, драйверы могут использовать текущее значение jiffies для расчёта интервалов времени между событиями (например, чтобы отличить двойной клик от одинарного в драйвере устройства ввода или вычисления времени ожидания). Одним словом, значения jiffies почти всегда достаточно, когда вам требуется измерять временные интервалы. Если требуются очень точные измерения для короткого промежутка времени, на помощь приходят процессорно-зависимые регистры (хотя они приносят серьёзные вопросы переносимости).

Вполне вероятно, что драйвер никогда не должен знать времени стенных часов, выраженного в месяцах, днях и часах; эта информация, как правило, необходима только пользовательским программам, таким, как cron и syslogd. Работу с реальным временем обычно лучше оставить пользовательскому пространству, где библиотека Си предлагает лучшую поддержку, кроме того, такой код часто слишком связан с политикой, чтобы принадлежать ядру. Однако, существует функция ядра, которая превращает время часов в значение jiffies:

#include 
unsigned long mktime (unsigned int year, unsigned int mon,
                      unsigned int day, unsigned int hour,
                      unsigned int min, unsigned int sec);

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

Хотя вы не будете иметь дело с человеко-читаемым представлением времени, иногда необходимо иметь дело с абсолютным временем даже в пространстве ядра. Для этого цели экспортирует функцию do_gettimeofday. При вызове она заполняет структуру timeval по указателю, который используется в системном вызове gettimeofday, знакомыми значениями секунд и микросекунд. Прототипом do_gettimeofday является:

#include 
void do_gettimeofday(struct timeval *tv);

Исходник утверждает, что do_gettimeofday имеет "разрешение около микросекунды", поскольку она запрашивает аппаратные средства  синхронизации, какая часть текущего тика уже прошла. Однако, точность варьируется от одной архитектуры к другой, поскольку она зависит от реального используемого аппаратного механизма. Например, некоторые m68knommu процессоры, системы Sun3 и других системы m68k не могут предложить больше, чем разрешение тика. Системы Pentium, с другой стороны, предлагают очень быстрые и точные измерения под-тиков через чтение счётчика тактов, описанное ранее в этой главе.

Текущее время также доступно (хотя и с точностью до тика) от переменной xtime, переменной из структуры timespec. Прямое использование этой переменной не рекомендуется, поскольку трудно получить атомарный доступ к обоим полям. Таким образом, ядро предоставляет вспомогательную функцию current_kernel_time:

#include 
struct timespec current_kernel_time(void);

Код для извлечения текущего времени разными способами можно получить из модуля jit (“just in time”, "точно в срок") в файлах исходных тектов на FTP сайте O'Reilly. jit создаёт файл, названный /proc/currentime, который возвращает при чтении следующие значения в ASCII:

Текущие значения jiffies и jiffies_64, как шестнадцатеричные числа;
Текущее время, возвращаемое do_gettimeofday;
timespec, возвращаемое current_kernel_time;

Мы решили использовать динамический файл /proc для сохранения шаблонного кода минимальным - не стоит создавать целое устройство только для возвращения небольшой текстовой информации.

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

phon% head -8 /proc/currentime
0x00bdbc1f 0x0000000100bdbc1f 1062370899.630126
                              1062370899.629161488
0x00bdbc1f 0x0000000100bdbc1f 1062370899.630150
                              1062370899.629161488
0x00bdbc20 0x0000000100bdbc20 1062370899.630208
                              1062370899.630161336
0x00bdbc20 0x0000000100bdbc20 1062370899.630233
                              1062370899.630161336

На вышеприведённом снимке экрана обратите внимание на две интересные вещи. Во-первых, значение current_kernel_time, хотя и выражено в наносекундах, имеет точность только до тика; do_gettimeofday постоянно сообщает позднее время, но не позднее чем следующий тик таймера. Во-вторых, 64-х разрядный счётчик тиков имеет установленным наименее значащий бит старшего 32-х битного слова. Это происходит потому, что значение по умолчанию для INITIAL_JIFFIES, используемое во время загрузки для инициализации счётчика, вызывает переполнение младшего слова через несколько минут после времени загрузки, чтобы помочь обнаружить проблемы, связанные с этим переполнением. Этот начальное смещение в счётчике не имеет никакого эффекта, поскольку jiffies не имеет отношения ко времени настенных часов. В /proc/uptime, когда ядро получает из счётчика время работы, перед преобразованием начальное смещение удаляется.

Комментариев нет:

Отправить комментарий

Примечание. Отправлять комментарии могут только участники этого блога.