linux kernel - Conversion de jiffies en milli secondes




github history (5)

Comment convertir manuellement des jiffies en millisecondes et vice versa sous Linux? Je sais que le noyau 2.6 a une fonction pour cela, mais je travaille sur 2.4 (devoirs) et bien que j'ai regardé le code, il utilise beaucoup de macro-constantes dont je n'ai aucune idée si elles sont définies en 2.4.


Answers

Réponse à # 3875801 peut aussi être révélateur


Comme une réponse précédente a dit, le taux auquel les augmentations de jiffies est fixé.

La méthode standard de spécification de l'heure pour une fonction qui accepte jiffies utilise la constante HZ .

C'est l'abréviation de Hertz, ou le nombre de ticks par seconde. Sur un système avec une coche de temporisation réglée sur 1ms, HZ = 1000. Certaines distributions ou architectures peuvent utiliser un autre numéro (100 était commun).

La manière standard de spécifier un nombre de jiffies pour une fonction utilise HZ , comme ceci:

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

Dans la plupart des cas, cela fonctionne très bien.

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 */

Cependant, ces deux derniers problèmes posent un problème, car sur un système avec une coche de temporisation de 10 ms, HZ/100 vaut 1 et la précision commence à en souffrir. Vous pouvez obtenir un délai entre 0,0001 et 1,999 ticks (0-2 ms, essentiellement). Si vous avez essayé d'utiliser HZ/200 sur un système de tick de 10ms, la division entière vous donne 0 jiffies!

Donc, la règle de base est, soyez très prudent en utilisant HZ pour les petites valeurs (ceux qui approchent 1 jiffie).

Pour convertir l'autre façon, vous utiliseriez:

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

Vous ne devriez pas espérer mieux que la précision en millisecondes.


J'ai trouvé cet exemple de code sur kernelnewbies . Assurez-vous de -lrt lien avec -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;
 }

Les Jiffies sont codés en dur dans Linux 2.4. Vérifiez la définition de HZ , qui est définie dans le param.h spécifique à l'architecture. C'est souvent 100 Hz, ce qui est une tique chaque (1 sec / 100 ticks * 1000 ms / sec) 10 ms.

Cela est vrai pour i386, et HZ est défini dans include/asm-i386/param.h .

Il y a des fonctions dans include/linux/time.h appelées timespec_to_jiffies et jiffies_to_timespec où vous pouvez convertir entre une struct timespec et des 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;
    }

Note: J'ai vérifié cette information dans la version 2.4.22.


USER_HZ été implémenté comme un compromis: bien que le code utilisateur puisse avoir une valeur codée en dur différente de USER_HZ , le noyau Linux avait historiquement une valeur HZ de 100 - donc pratiquement toutes les valeurs HZ codées en dur dans le code utilisateur existant avaient été fixées à 100 .

Voici l'essence de ce qui est arrivé:

The Linux kernel used to have HZ set at a constant 100 for all
architectures. As additional architecture support was added, the HZ
value became variable: e.g. Linux on one machine could have a HZ
value of 1000 while Linux on another machine could have a HZ value
of 100.

This possibility of a variable HZ value caused existing user code,
which had hardcoded an expectation of HZ set to 100, to break due to
the exposure in userspace of kernel jiffies which may have be based
on a HZ value that was not equal to 100.

To prevent the chaos that would occur from years of existing user
code hardcoding a constant HZ value of 100, a compromise was made:
any exposure of kernel jiffies to userspace should be scaled via a
new USER_HZ value -- thus preventing existing user code from
breaking on machines with a different HZ value, while still allowing
the kernel on those machines to have a HZ value different from the
historic 100 value.

Maintenant, cela laisse la question de savoir pourquoi certains jiffies du noyau sont exposés à l'espace utilisateur non mis à l'échelle (par exemple dans /proc/timer_list ). Thomas Gleixner explique :

Toutes les instances qui sont de facto des API, syscalls et divers fichiers dans proc / doivent être dans USER_HZ car les applications userspace dépendent de la valeur USER_HZ.

proc / timer_list est exempté de cela parce que c'est plus une interface de débogage qui ne fait pas partie de l'API stricte du noyau. Et nous voulons vraiment voir les vraies valeurs et non celles mises à l'échelle USER_HZ à cette fin. J'espère que cela répond à votre question.

Donc, toutes les instances qui font partie de l'API stricte du noyau sont destinées à faire évoluer les jiffies du noyau via USER_HZ avant l'exposition à l'espace utilisateur, dont les autres instances sont exemptées.

Voir également

La section Tick Rate: HZ de Linux Kernel Development Deuxième édition par Robert Love





linux linux-kernel