Преобразование jiffies в миллисекунды

Как вручную конвертировать jiffies в миллисекунды и наоборот в Linux? Я знаю, что у ядра 2.6 есть функция для этого, но я работаю над 2.4 (домашнее задание), и хотя я смотрел на код, он использует множество макроконстантов, о которых я понятия не имею, если они определены в 2.4.

Ответ 1

Как было сказано в предыдущем ответе, скорость, с которой приращения jiffies фиксированы.

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

Это аббревиатура для Hertz или количество тиков в секунду. В системе с таймером, установленным в 1 мс, HZ = 1000. В некоторых дистрибутивах или архитектурах может использоваться другое число (обычно используется 100).

Стандартный способ указывать счетчик jiffies для функции - это использовать HZ, например:

schedule_timeout(HZ / 10);  /* Timeout after 1/10 second */

В большинстве простых случаев это прекрасно работает.

2*HZ     /* 2 seconds in jiffies */
HZ       /* 1 second in jiffies */
foo * HZ /* foo seconds in jiffies */
HZ/10    /* 100 milliseconds in jiffies */
HZ/100   /* 10 milliseconds in jiffies */
bar*HZ/1000 /* bar milliseconds in jiffies */
Тем не менее, последние два имеют небольшую проблему, как в системе с таймером таймера 10 мс, HZ/100 равно 1, и точность начинает страдать. Вы можете получить задержку где-то между отметками таймера 0.0001 и 1.999 (по существу, 0-2 мс). Если вы попытались использовать HZ/200 в системе с отметкой 10 мс, целочисленное деление даст вам 0 jiffies!

Итак, эмпирическое правило: будьте очень осторожны, используя HZ для маленьких значений (приближающихся к 1 jiffie).

Чтобы преобразовать другой способ, вы должны использовать:

jiffies / HZ          /* jiffies to seconds */
jiffies * 1000 / HZ   /* jiffies to milliseconds */

Вы не должны ожидать ничего лучше, чем миллисекундная точность.

Ответ 2

Jiffies жестко закодированы в Linux 2.4. Проверьте определение HZ, которое определено в param.h для архитектуры. Часто это 100 Гц, каждый галочка (1 с /100 тиков * 1000 мс/сек) 10 мс.

Это справедливо для i386, а HZ определяется в include/asm-i386/param.h.

В include/linux/time.h есть функции, называемые timespec_to_jiffies и jiffies_to_timespec, где вы можете конвертировать назад и вперед между struct timespec и jiffies:

    #define MAX_JIFFY_OFFSET ((~0UL >> 1)-1)

    static __inline__ unsigned long
    timespec_to_jiffies(struct timespec *value)
    {
            unsigned long sec = value->tv_sec;
            long nsec = value->tv_nsec;

            if (sec >= (MAX_JIFFY_OFFSET / HZ))
                    return MAX_JIFFY_OFFSET;
            nsec += 1000000000L / HZ - 1;
            nsec /= 1000000000L / HZ;
            return HZ * sec + nsec;
    }

    static __inline__ void
    jiffies_to_timespec(unsigned long jiffies, struct timespec *value)
    {
            value->tv_nsec = (jiffies % HZ) * (1000000000L / HZ);
            value->tv_sec = jiffies / HZ;
    }

Примечание: Я проверил эту информацию в версии 2.4.22.

Ответ 3

Я нашел этот пример кода на kernelnewbies. Убедитесь, что вы ссылаетесь на -lrt

#include <unistd.h>
#include <time.h>
#include <stdio.h>

int main()
{
    struct timespec res;
    double resolution;

    printf("UserHZ   %ld\n", sysconf(_SC_CLK_TCK));

    clock_getres(CLOCK_REALTIME, &res);
    resolution = res.tv_sec + (((double)res.tv_nsec)/1.0e9);

    printf("SystemHZ %ld\n", (unsigned long)(1/resolution + 0.5));
    return 0;
 }