Точность отметки времени на EXT4 (менее миллисекунды)

Я писал код в Vala, где сначала получал системное время, затем создавал файл, а затем извлекал метку времени этого файла. Временная метка всегда будет раньше системного времени, где-то между 500 и 1500 микросекундами, что не имеет смысла.

Затем я написал простой сценарий оболочки:

while true; do
touch ~/tmp/fred.txt
stat ~/tmp/fred.txt|grep ^C
done

Со следующим результатом:

Change: 2013-01-18 16:02:44.290787250 +1100
Change: 2013-01-18 16:02:44.293787250 +1100
Change: 2013-01-18 16:02:44.296787250 +1100
Change: 2013-01-18 16:02:44.298787248 +1100
Change: 2013-01-18 16:02:44.301787248 +1100
Change: 2013-01-18 16:02:44.304787248 +1100
Change: 2013-01-18 16:02:44.306787248 +1100
Change: 2013-01-18 16:02:44.309787248 +1100
Change: 2013-01-18 16:02:44.312787248 +1100
Change: 2013-01-18 16:02:44.315787248 +1100

Как видите, первые 3 цифры после десятичной точки (миллисекунды) выглядят нормально, так как они увеличиваются, как и ожидалось, но 4-я цифра и далее выглядят неправильно. Кажется, что с 4-го по 9-й цифры идет медленный обратный отсчет. Есть ли какая-то причина для этого, хотя я думаю, что ext4 поддерживает с точностью до нано секунды. Метки времени доступа и изменения ведут себя одинаково.

2 ответа

Решение

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

Внутри файловая система ext4 вызывает код current_fs_time() который является текущим кэшированным временем ядра, усеченным до временной детализации, указанной в суперблоке файловой системы, которая для ext4 равна 1 нс.

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

Попробуйте это и посмотрите, получаете ли вы также результаты, аналогичные вашим статистическим вызовам:

while true; do date --rfc-3339=ns; done

На моей машине (amd64, intel virtualbox) квантования нет.

например

2013-01-18 17:04:21.097211836+11:00
2013-01-18 17:04:21.098354731+11:00
2013-01-18 17:04:21.099282128+11:00
2013-01-18 17:04:21.100276327+11:00
2013-01-18 17:04:21.101348507+11:00
2013-01-18 17:04:21.102516837+11:00

Обновление:

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

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

Размер индексного дескриптора по умолчаниюmkfs.ext4зависит от вашего дистрибутива. Некоторые дистрибутивы «маломощных систем» по-прежнему используют 128 байт для экономии дискового пространства. А в некоторых других дистрибутивах также есть правило: «если размер раздела меньше 512 МБ, используйте 128-байтовые индексные дескрипторы».

Наличие 128-байтовых индексных дескрипторов означает, что файловая система будет иметь метки времени с точностью до 1 секунды (без десятичных знаков). Это также означает, что файловая система не будет поддерживать ACL, метки SELinux и т. д. Наиболее серьезно из всех 128-байтовые индексные дескрипторы (временные метки второй точности) страдают от ошибки Y2K38, а это означает, что временные метки после 2038 года не поддерживаются.

Вы можете вручную установить размер индексного дескриптора с помощьюmkfs.ext4 -I 256при форматировании. Вы также можете изменить его позже черезtune2fs -I 256 /dev/<the_device>в существующей файловой системе.

Другие вопросы по тегам