SCHED(7)

NOM
sched - aperçu des API d'ordonnancement

DESCRIPTION

  Résumé des API
Les API d'ordonnancement de Linux sont les suivantes :

sched_setscheduler(2)
    Affecte la politique d'ordonnancement et les paramètres associés du thread indiqué.

sched_getscheduler(2)
    Renvoie la politique d'ordonnancement du thread indiqué.

sched_setparam(2)
    Affecte les paramètres d'ordonnancement du thread indiqué.

sched_getparam(2)
    Récupère les paramètres d'ordonnancement du thread indiqué.

sched_get_priority_max(2)
    Renvoie la priorité la plus basse disponible pour la politique d'ordonnancement indiquée.

sched_get_priority_min(2)
    Renvoie la priorité la plus haute disponible pour la politique d'ordonnancement indiquée.

sched_rr_get_interval(2)
    Récupère le quantum utilisé pour les threads qui sont ordonnancés par une politique de type « round robin ».

sched_yield(2)
    Entraîne la libération de la CPU par l'appelant afin de permettre à d'autres thread de s'exécuter.

sched_setaffinity(2)
    (propre à Linux) Définit le maque d'affinité CPU du thread indiqué.

sched_getaffinity(2)
    (propre à Linux) Récupère le maque d'affinité CPU du thread indiqué.

sched_setattr(2)
    Définit la politiques d'ordonnancement et les paramètres du thread indiqué. Cet appel système (propre à Linux) fournit un sur-ensemble de la fonctionnalité de sched_setscheduler(2) et de sched_setparam(2).

sched_getattr(2)
    Récupère la politique d'ordonnancement et les paramètres du thread indiqué. Cet appel système (propre à Linux) fournit un sur-ensemble de la fonctionnalité de sched_getscheduler(2) et de sched_getparam(2).

  Politiques d'ordonnancement
L'ordonnanceur est la partie du noyau qui décide quel thread prêt va être exécuté ensuite. Chaque processus a une politique d'ordonnancement associée et une priorité d'ordonnancement statique, sched_priority. L'ordonnanceur prend ses décisions en fonction de la politique d'ordonnancement et de la priorité statique de tous les threads du système. Pour les threads ordonnancés sous l'une des politiques d'ordonnancement normales (SCHED_OTHER, SCHED_IDLE, SCHED_BATCH), sched_priority n'est pas utilisée dans les décisions d'ordonnancement (et doit valoir 0). Les processus ordonnancés sous l'une des politiques d'ordonnancement temps réel (SCHED_FIFO, SCHED_RR) ont une valeur de sched_priority dans l'intervalle 1 (faible) à 99 (haute). (Comme les nombres l'impliquent, les threads temps réel ont toujours une priorité plus haute que les threads normaux.) Notez bien : POSIX.1-2001 exige seulement d'une implémentation qu'elle gère un minimum de 32 niveaux de priorité distincts pour les politiques temps réel et certains systèmes n'offrent que ce minimum. Les programmes portables doivent utiliser sched_get_priority_min(2) et sched_get_priority_max(2) pour connaître l'intervalle des priorités gérées pour une politique particulière. Conceptuellement, l'ordonnanceur dispose d'une liste de tous les threads prêts pour chaque valeur possible de sched_priority. Afin de déterminer quel processus doit s'exécuter ensuite, l'ordonnanceur recherche la liste non vide de plus haute priorité statique et choisit le thread en tête de cette liste. La politique d'ordonnancement d'un thread détermine l'emplacement où il sera inséré dans la liste contenant les threads de même priorité statique, et comment il se déplacera dans cette liste. Tout ordonnancement est préemptif : si un thread avec une priorité statique plus élevée devient prêt, le thread actuellement en cours d'exécution est interrompu et retourne dans la liste d'attente avec son niveau de priorité statique. La politique d'ordonnancement détermine simplement l'ordre utilisé dans une liste de threads prêts avec des priorités statiques égales.

  SCHED_FIFO : Ordonnancement First In-First Out (premier arrivé, premier servi)
SCHED_FIFO ne peut être utilisée qu'avec des priorités statiques supérieures à 0, ce qui signifie que dès qu'un thread SCHED_FIFO devient prêt, un thread normal SCHED_OTHER, SCHED_BATCH ou SCHED_IDLE en cours d'exécution sera interrompu. SCHED_FIFO est un ordonnancement simple sans tranches de temps. Pour les threads ordonnancés par SCHED_FIFO les règles suivantes sont appliquées :

*   Un thread SCHED_FIFO qui a été préempté par un autre thread de priorité supérieure restera en tête de sa liste et reprendra son exécution dès que tous les threads de priorités supérieures sont à nouveau bloqués.

*   Quand un thread SCHED_FIFO devient prêt, il est inséré à la fin de sa liste.

*   Un appel système sched_setscheduler(), sched_setparam(2) ou sched_setattr(2) placera le thread SCHED_FIFO (ou SCHED_RR) identifié par pid en tête de sa liste s'il est prêt. Il pourra donc stopper le thread en cours d'exécution si sa priorité est au moins aussi grande. (Selon POSIX.1-2001, le thread devrait aller à la fin de sa liste.)

*   Un thread appelant sched_yield(2) sera placé à la fin de sa liste.

Aucun autre événement ne modifiera l'ordre des listes de priorités statiques égales avec SCHED_FIFO. Un thread SCHED_FIFO s'exécute jusqu'à ce qu'il soit bloqué par une opération d'entrée-sortie, qu'il soit préempté par un thread de priorité supérieure, ou qu'il appelle sched_yield(2).

  SCHED_RR : Ordonnancement Round Robin
SCHED_RR est une amélioration simple de la politique SCHED_FIFO. Tout ce qui est décrit pour SCHED_FIFO s'applique aussi à SCHED_RR, sauf que chaque thread ne dispose que d'une tranche temporelle limitée pour son exécution. Si un thread sous politique SCHED_RR s'est exécuté depuis une durée supérieure ou égale à la tranche temporelle (time quantum), il sera placé à la fin de la liste de sa priorité. Un thread sous SCHED_RR qui a été préempté par un thread de priorité supérieure terminera sa tranche de temps lorsqu'il reprendra son exécution. La longueur du quantum de temps peut être lue avec sched_rr_get_interval(2).

  SCHED_DEADLINE: ordonnancement sur échéances selon le modèle des tâches sporadiques.
Depuis la version 3.14, Linux offre une politique d'ordonnancement sur échéances (SCHED_DEADLINE). L'implémentation actuelle de cette politique repose sur les algorithmes GEDF (Global Earliest Deadline First, ou « priorité globale à l'échéance proche ») et CBS (Constant Bandwidth Server, ou « serveur à bande passante constante ») utilisés conjointement. Pour définir ou récupérer cette politique et ses attributs associés, on doit utiliser les appels système sched_setattr(2) et sched_getattr(2) Une tâche sporadique présente une séquence de sous-tâches qui sont chacune activées au moins une fois par période. Chaque sous-tâche a également une échéance relative, avant laquelle elle doit achever son exécution, et un temps d'exécution, qui est le temps CPU nécessaire qu'elle s'exécute. Le moment auquel une tâche est activée parce qu'une sous-tâche doit être exécutée est appelé temps d'activation (également désigné temps d'appel (« request time ») ou temps de libération (« release time »)). Le temps de lancement est le moment auquel la tâche commence son exécution. L'échéance impérative est obtenue en additionnant l'échéance relative et le temps d'activation. Le schéma suivant illustre ces termes :
activation/réveil                    échéance impérative
     |    temps du lancement                   |
     |        |                                |
     v        v                                v
-----x--------xoooooooooooooooooooooooo--------x--------x---
              |<- temps d'exécution ->|
     |<---------- échéance relative ---------->|
     |<----------------- période ---------------------->|
Lorsqu'une politique SCHED_DEADLINE est activée au moyen de sched_setattr(2), il est possible de préciser trois paramètres : Runtime, Deadline et Period. Ces paramètres ne correspondent pas forcément aux termes décrits précédemment : il est d'usage d'affecter à Runtime une valeur supérieure au temps d'exécution moyen (ou le pire temps d'exécution possible, pour les cas de temps réel extrêmes) ; Deadline prend la valeur de l'échéance relative ; enfin, Period reçoit la valeur de la période de la tâche. Ainsi, pour un ordonnancement SCHED_DEADLINE, on obtient.
activation/réveil                    échéance impérative
     |    temps du lancement                   |
     |        |                                |
     v        v                                v
-----x--------xoooooooooooooooooooooooo--------x--------x---
              |<------- Exécution ------->|
     |<----------------- Échéance ------------>|
     |<----------------- Période ---------------------->|
Les trois paramètres de configuration de l'ordonnancement sur échéances correspondent aux champs sched_runtime, sched_deadline et sched_period de la structure sched_attr (consultez sched_setattr(2)). Ces champs sont exprimés en nanosecondes. Si la valeur 0 est affectée à sched_period, ce paramètre prend la valeur de sched_deadline. Le noyau exige que :
    sched_runtime <= sched_deadline <= sched_period De plus, dans l'implémentation actuelle, tous les paramètres doivent valoir au moins 1024 (c'est à dire à peine plus qu'une microseconde, qui est la résolution de cette implémentation) et moins de 2^63. Si la valeur de l'un de ces paramètres sort de cet intervalle, sched_setattr(2) échoue en renvoyant l'erreur EINVAL. CBS assure que le différentes tâches n'interfèrent pas en bloquant les threads qui tentent de dépasser leur temps d'exécution (Runtime). Pour que les conditions requises par l'ordonnancement sur échéances sont assurées, le noyau doit empêcher des situations dans lesquelles SCHED_DEADLINE est fixé à une valeur inatteignable (c'est à dire qu'il est impossible d'ordonnancer le thread) en tenant compte des contraintes données. Le noyau doit donc exécuter un test d'approbation lorsque la politique SCHED_DEADLINE et ses attributs sont définis ou modifiés. Ce test d'approbation valide que le changement demandé est réalisable ; si ce n'est pas le cas, sched_setattr(2) échoue et renvoie l'erreur EBUSY. Par exemple, il est nécessaire (et par forcément suffisant) pour l'utilisation totale d'être inférieure ou égale au nombre total de CPU disponibles, où (puisque chaque thread peut s'exécuter au plus pendant son d'exécution (Runtime) pour chaque période) l'utilisation pour ce thread vaut Runtime divisé par Period. Pour assurer les conditions qui sont requises lorsqu'un thread est autorisé à utiliser la politique SCHED_DEADLINE, les threads ordonnancés selon SCHED_DEADLINE ont la priorité la plus élevée parmi tous les threads (contrôlables par l'utilisateur) du système ; si un thread ordonnancé selon SCHED_DEADLINE est exécutable, il aura la priorité sur tout autre thread ordonnancé par une autre politique. Un appel à fork(2) effectué par un thread ordonnancé selon la politique SCHED_DEADLINE échouera en renvoyant l'erreur EAGAIN, sauf dans le cas ou l'attribut reset-on-fork du thread est activé (voir plus bas). Un thread ordonnancé selon SCHED_DEADLINE qui appelle sched_yield(2) cédera la priorité à la tâche en cours et attendra de début d'une nouvelle période.

  SCHED_OTHER : Ordonnancement temps-partagé par défaut
La politique SCHED_OTHER ne peut être utilisée qu'avec des priorités statiques à 0. C'est la politique standard de l'ordonnanceur temps partagé de Linux, et est conçue pour tous les thread ne réclamant pas de fonctionnalités temps-réel. Le thread à exécuter est choisi dans la liste des threads de priorités statiques nulles, en utilisant une priorité dynamique qui ne s'applique que dans cette liste. La priorité dynamique est basée sur la valeur de « politesse » du thread (définie avec les appels système nice(2), setpriority(2) ou sched_setattr(2)) et est incrémentée à chaque quantum de temps où le thread est prêt mais non sélectionné par l'ordonnanceur. Ceci garantit une progression équitable de tous les thread SCHED_OTHER.

  SCHED_BATCH : Ordonnancement de processus de traitement par lots
(Depuis Linux 2.6.16) SCHED_BATCH ne peut être utilisée qu'avec une priorité statique de 0. Cette politique est similaire à SCHED_OTHER, en ce qu'elle ordonnance les threads conformément à leur priorité dynamique (basée sur la valeur de politesse). La différence est que cette politique fera que l'ordonnanceur considérera toujours que ce thread demande beaucoup de ressources processeur. Par conséquent, il lui appliquera une pénalité d'ordonnancement vis-à-vis du comportement au réveil, et le thread sera légèrement désavantagé dans les décisions d'ordonnancement. Cette politique est utile pour les processus non interactifs, mais qui ne souhaitent pas diminuer leur valeur de politesse, ou pour ceux qui veulent une politique d'ordonnancement déterministe, sans que l'interactivité ne cause de préemptions supplémentaires.

  SCHED_IDLE : Ordonnancement de tâches de très faible priorité
(Depuis Linux 2.6.23.) SCHED_IDLE ne peut être utilisée qu'avec une priorité statique de 0 ; la valeur de courtoisie n'a pas d'influence pour cette politique. Cette politique est conçue pour l'exécution de tâches de très faible priorité (inférieure même à une valeur de courtoisie +19 dans les politiques SCHED_OTHER ou SCHED_BATCH).

  Réinitialiser la politique d'ordonnancement pour les processus fils
Chaque thread possède un attribut d'ordonnancement reset-on-fork. Lorsque cet attribut est défini, les fils créés au moyen de fork(2) n'héritent pas des politiques d'ordonnancement nécessitant des droits. L'attribut reset-on-fork peut être défini soit :

*   En appliquant un ou logique (OR) de l'attribut SCHED_RESET_ON_FORK dans l'argument policy au moment de l'appel à sched_setscheduler(2) (à partir de Linux 2.6.32); soit

*   en ajoutant l'argument SCHED_FLAG_RESET_ON_FORK dans attr.sched_flags au moment de l'appel à sched_setattr(2).

Notez que les constantes utilisées dans ces deux APIs ont des noms différents. La disposition de l'attribut reset-on-fork peut, de façon analogue, être obtenue au moyen de sched_getscheduler(2) et de sched_getattr(2). La fonctionnalité reset-on-fork est prévue pour des applications de lecture audiovisuelle, et peut être utilisée pour empêcher les applications de passer outre la limite de ressource RLIMIT_RTTIME (consultez getrlimit(2)) en créant de nombreux processus fils. Plus précisément, si l'attribut reset-on-fork est utilisé, les règles suivantes seront appliquées lors de la création ultérieure des fils :

*   Si le thread appelant a une politique d'ordonnancement SCHED_FIFO ou SCHED_RR, la politique pour les processus fils est réinitialisée à SCHED_OTHER.

*   Si le processus appelant a une valeur de politesse négative, elle est mise à zéro pour les processus fils.

Une fois que l'attribut reset-on-fork est activé, il ne peut être désactivé que si le thread possède la capacité CAP_SYS_NICE. Cet attribut est désactivé pour les processus fils créés avec fork(2).

  Privilèges et limites de ressources
Avec les noyaux Linux antérieurs à 2.6.12, seuls les threads privilégiés (CAP_SYS_NICE) pouvaient attribuer une priorité statique non nulle (c'est-à-dire définir une politique d'ordonnancement temps réel). Le seul changement qu'un thread non privilégié pouvait faire était d'affecter la politique SCHED_OTHER, et seulement si l'UID effectif de l'appelant était le même que l'UID réel ou effectif du thread cible (c'est-à-dire le thread spécifié par pid), dont la politique est modifiée. Un thread doit avoir des droits spécifiques (CAP_SYS_NICE) pour pouvoir affecter ou modifier la politique SCHED_DEADLINE. Depuis Linux 2.6.12, la limite de ressources RLIMIT_RTPRIO définit un plafond pour la priorité statique d'un thread non privilégié pour les politiques SCHED_RR et SCHED_FIFO. Les règles pour modifier la politique d'ordonnancement et la priorité sont les suivantes :

*   Si un thread non privilégié a une limite souple RLIMIT_RTPRIO non nulle, il peut modifier sa politique et sa priorité d'ordonnancement, à condition que la priorité reste inférieure au maximum de sa priorité actuelle et à la limite souple RLIMIT_RTPRIO.

*   Si la limite souple RLIMIT_RTPRIO est nulle, les seules modifications permises sont une diminution de la priorité ou bien un basculement vers une politique qui ne soit pas temps réel.

*   Soumis aux mêmes règles, un autre thread non privilégié peut également faire ces modifications à partir du moment où l'UID effectif du thread effectuant la modification correspond à l'UID réel ou effectif du thread cible.

*   Des règles particulières s'appliquent à la politique SCHED_IDLE. Dans les noyaux Linux antérieurs à 2.6.39, un thread non privilégié opérant sous cette politique ne peut pas modifier sa politique, quelle que soit la valeur de sa limite souple de ressources RLIMIT_RTPRIO. Dans les noyaux Linux postérieurs à 2.6.39, un thread non privilégié peut basculer vers la politique SCHED_BATCH ou SCHED_NORMAL tant que sa valeur de politesse tombe dans l'intervalle permis par sa limite de ressources RLIMIT_NICE (consultez getrlimit(2)).

Les threads privilégiés (CAP_SYS_NICE) ignorent la limite RLIMIT_RTPRIO : comme avec d'anciens noyaux, ils peuvent modifier arbitrairement la politique d'ordonnancement et la priorité. Consultez getrlimit(2) pour plus d'informations sur RLIMIT_RTPRIO.

  Limiter l'utilisation CPU des processus temps-réel et à échéances.
Une boucle sans fin non bloquante dans un thread ordonnancé selon une politique SCHED_FIFO, SCHED_RR ou SCHED_DEADLINE bloquera indéfiniment tous les threads ayant une priorité plus faible. Avant Linux 2.6.25, le seul moyen d'éviter qu'un processus temps-réel hors de contrôle ne bloque le système était d'exécuter (sur la console) un shell ayant un priorité statique supérieure à celle de l'application testée. Cela permettait d'exécuter en urgence une commande kill sur les applications temps-réel en cours de test qui ne se suspendaient ou ne se terminaient pas comme prévu. A partir de Linux 2.6.25, il existe d'autres techniques pour traiter le cas des processus temps-réel et à échéances qui sont hors de contrôle. L'une de ces techniques consiste à utiliser la limite de ressources RLIMIT_RTTIME pour définir la limite du temps CPU qu'un processus temps-réel a le droit de consommer. Consultez getrlimit(2) pour plus de détails. A partir de la version 2.6.25, Linux propose également deux fichiers /proc qui peuvent être utilisés pour réserver une certaine quantité de temps CPU aux processus non temps-réel. La réservation de temps CPU par ce moyen permet d'allouer du temps CPU, par exemple, à un shell root qui puisse exécuter une commande kill sur un processus hors de contrôle. Ces deux fichiers définissent des valeurs exprimées en microsecondes :

/proc/sys/kernel/sched_rt_period_us
    Le fichier définit une période d'ordonnancement correspondant à 100% de la bande passante de la CPU. La valeur contenue dans ce fichier peut aller de 1 à INT_MAX, soit une durée allant de 1 microseconde à environ 35 minutes. La valeur par défaut contenue dans ce fichier est 1 000 000 (1 seconde).

/proc/sys/kernel/sched_rt_runtime_us
    La valeur contenue dans ce fichier définit quelle part d'une « période » peut être utilisée par des processus temps-réel et à échéances. La valeur contenue dans ce fichier peut aller de -1 à INT_MAX- 1. -1 fixe un temps d'exécution (runtime) égal à la période, c'est à dire qu'aucun temps CPU n'est réservé pour les processus non temps-réel (ce qui correspond au comportement de Linux avant la version 2.6.25 du noyau). La valeur par défaut contenue dans ce fichier est 950 000 (0,95 secondes), ce qui signifie que 5% du temps CPU est réservé aux processus qui ne s'exécutent pas selon une politique d'ordonnancement temps-réel ou à échéances.

  Temps de réponse
Un thread de haute priorité bloqué en attente d'entrées-sorties est affecté d'un certain temps de réponse avant d'être sélectionné à nouveau. Le concepteur d'un gestionnaire de périphérique peut réduire grandement ce temps de réponse en utilisant un gestionnaire d'interruptions lentes.

  Divers
Les processus fils héritent de la politique d'ordonnancement et des paramètres associés lors d'un fork(2). L'algorithme et les paramètres d'ordonnancement sont conservés au travers d'un execve(2). Le verrouillage de pages en mémoire est généralement nécessaire pour les processus temps réel afin d'éviter les délais de pagination ; ceci peut être effectué avec mlock(2) ou mlockall(2).

NOTES

À l'origine, le noyau Linux standard visait un système d'exploitation à vocation généraliste, devant gérer des processus en arrière-plan, des applications interactives, et des applications en temps réel souple (qui ont besoin en général de répondre à des critères de temps maximal). Bien que le noyau Linux 2.6 ait permis la préemption du noyau et que le nouvellement introduit ordonnanceur O(1) assure que le temps nécessaire pour planifier soit fixe et déterministe quel que soit le nombre de tâches, une vraie gestion temps réel n'était pas possible avant le noyau 2.6.17.

  Fonctionnalités temps réel dans le noyau Linux principal
Toutefois, depuis le noyau 2.6.18, Linux s'est vu graduellement équipé de possibilités temps réel, la plupart étant dérivées des ajouts de préemption temps réel (realtime-preempt) réalisés par Ingo Molnar, Thomas Gleixner, Steven Rostedt et autres. Jusqu'à ce que ces ajouts aient été entièrement fusionnés dans le noyau principal (c'est attendu aux alentours des versions 2.6.30), ils doivent être installés pour atteindre les meilleures performances temps réel. Ces ajouts s'appellent :
patch-version-noyau-rtversion-patch

et peuvent être téléchargés à partir de http://www.kernel.org/pub/linux/kernel/projects/rt/. Sans les ajouts et avant leur complète inclusion dans le noyau principal, la configuration du noyau n'offre que trois classes de préemption CONFIG_PREEMPT_NONE, CONFIG_PREEMPT_VOLUNTARY et CONFIG_PREEMPT_DESKTOP qui fournissent respectivement « aucune », « quelque » et une « considérable » réduction de la latence d'ordonnancement de pire cas. Avec les ajouts appliqués ou après leur pleine inclusion dans le noyau principal, la configuration supplémentaire CONFIG_PREEMPT_RT devient disponible. Si elle est choisie, Linux est transformé en un système d'exploitation temps réel ordinaire. Les politiques d'ordonnancement FIFO et RR sont alors utilisées pour lancer un thread avec une vraie priorité temps réel et une latence minimum d'ordonnancement de pire cas.

VOIR AUSSI
chrt(1), getpriority(2), mlock(2), mlockall(2), munlock(2), munlockall(2), nice(2), sched_get_priority_max(2), sched_get_priority_min(2), sched_getscheduler(2), sched_getaffinity(2), sched_getparam(2), sched_rr_get_interval(2), sched_setaffinity(2), sched_setscheduler(2), sched_setparam(2), sched_yield(2), setpriority(2), pthread_getaffinity_np(3), pthread_setaffinity_np(3), sched_getcpu(3), capabilities(7), cpuset(7)

Programming for the real world - POSIX.4 de Bill O. Gallmeister, O'Reilly & Associates, Inc., ISBN 1-56592-074-0.

Les fichiers source du noyau Linux Documentation/scheduler/sched-deadline.txt, Documentation/scheduler/sched-rt-group.txt, Documentation/scheduler/sched-design-CFS.txt et Documentation/scheduler/sched-nice-design.txt

COLOPHON
Cette page fait partie de la publication 3.70 du projet man-pages Linux. Une description du projet et des instructions pour signaler des anomalies peuvent être trouvées à l'adresse http://www.kernel.org/doc/man-pages/.

TRADUCTION
Depuis 2010, cette traduction est maintenue à l'aide de l'outil po4a <http://po4a.alioth.debian.org/> par l'équipe de traduction francophone au sein du projet perkamon <http://perkamon.alioth.debian.org/>.

Veuillez signaler toute erreur de traduction en écrivant à <perkamon-fr@traduc.org>.

Vous pouvez toujours avoir accès à la version anglaise de ce document en utilisant la commande « LC_ALL=C man <section> <page_de_man> ».