Man page - cpuset(7)

Packages contains this manual

Available languages:

en fr ru

Manual

cpuset

NOM
DESCRIPTION
FICHIERS
CAPACITÉS ÉTENDUES
Ensembles de CPU exclusifs
Hardwall
Notification à la libération
Pression mémoire
Répartition mémoire
Migration mémoire
RĂ©partition de la charge par l’ordonnanceur
Niveau du domaine de dĂ©tente de l’ordonnanceur
FORMATS
Affichage sous forme de masque
Affichage sous forme de liste
RÈGLES
PERMISSIONS
AVERTISSEMENTS
Activation de memory_pressure
Utilisation de la commande echo
EXCEPTIONS
Placement mémoire
Renommer des cpusets
ERREURS
VERSIONS
NOTES
BOGUES
EXEMPLES
CrĂ©er et s’attacher Ă  un cpuset.
DĂ©placer des tĂąches sur d’autres nƓuds mĂ©moire.
VOIR AUSSI
TRADUCTION

NOM

cpuset - Confiner des processus Ă  des sous-ensembles de processeurs et de nƓuds mĂ©moire

DESCRIPTION

Le systĂšme de fichiers cpuset (N.d.T. : « cpuset » signifie mot Ă  mot « ensemble de CPU », mais comme il ne s’agit pas uniquement d’ensembles de CPU, le terme cpuset sera utilisĂ© par la suite) est une interface sous forme d’un pseudosystĂšme de fichiers pour le mĂ©canisme « cpuset » du noyau, qui permet de contrĂŽler le placement de processus sur des processeurs ou en mĂ©moire. Il est habituellement montĂ© dans /dev/cpuset .

Sur les systĂšmes dont le noyau a Ă©tĂ© compilĂ© avec la prise en charge des cpusets, tous les processus sont attachĂ©s Ă  un cpuset, et les cpusets sont toujours prĂ©sents. Si un systĂšme prend en charge les cpusets, alors il aura une entrĂ©e nodev cpuset dans le fichier /proc/filesystems . En montant le systĂšme de fichiers cpuset (consultez la section EXEMPLE ci-dessous), l’administrateur peut configurer les cpusets d’un systĂšme pour contrĂŽler le placement des processus sur les CPU et dans la mĂ©moire sur de systĂšme. Par dĂ©faut, si la configuration des cpusets d’un systĂšme n’est pas modifiĂ©e ou si le systĂšme de fichiers cpuset n’est mĂȘme pas montĂ©, le mĂ©canisme des cpusets, mĂȘme s’il est prĂ©sent, n’a pas d’effets sur le comportement du systĂšme.

Un cpuset dĂ©finit une liste de CPU et de nƓuds mĂ©moire.

Les CPU d’un systĂšme comprennent toutes les unitĂ©s de traitement logiques sur lesquelles peuvent s’exĂ©cuter des processus, comprenant, s’il y en a, les diffĂ©rents cƓurs d’un processeur et les Hyper-Threads d’un cƓur de processeur. Les nƓuds mĂ©moire comprennent tous les bancs distinct de mĂ©moire ; les petits systĂšmes et les systĂšmes SMP ont typiquement un seul nƓud mĂ©moire qui contient toute la mĂ©moire du systĂšme, alors que les systĂšmes NUMA (« non-uniform memory access » : accĂšs non uniforme Ă  la mĂ©moire) ont plusieurs nƓuds mĂ©moire.

Les cpusets sont reprĂ©sentĂ©s par des rĂ©pertoires dans un pseudosystĂšme de fichiers hiĂ©rarchique dont le rĂ©pertoire de plus haut niveau ( /dev/cpuset ) reprĂ©sente le systĂšme complet (tous les CPU et nƓuds mĂ©moire en ligne). Tout cpuset fils (le descendant) d’un autre cpuset pĂšre contient un sous-ensemble des CPU et des nƓuds mĂ©moire du pĂšre. Les rĂ©pertoires et les fichiers qui reprĂ©sentent les cpusets ont les permissions habituelles des systĂšmes de fichiers.

Chaque processus du systĂšme appartient Ă  un unique cpuset. Un processus est obligĂ© de s’exĂ©cuter sur les CPU du cpuset auquel il appartient et est obligĂ© d’allouer de la mĂ©moire uniquement sur les nƓuds mĂ©moire de ce cpuset. Quand un processus crĂ©e un fils avec fork (2), le processus fils est placĂ© dans le mĂȘme cpuset que le processus pĂšre. S’il a les privilĂšges suffisants, le processus fils peut se dĂ©placer d’un cpuset Ă  un autre et les CPU ou nƓuds mĂ©moire d’un cpuset existant peuvent ĂȘtre changĂ©s.

Au dĂ©but du dĂ©marrage du systĂšme, un seul cpuset est dĂ©fini qui comprend tous les CPU et tous les nƓuds mĂ©moire du systĂšme et tous les processus se trouvent dans ce cpuset. Pendant le dĂ©marrage ou par la suite lors de l’exĂ©cution normale du systĂšme, d’autres cpusets peuvent ĂȘtre créés, en tant que sous-rĂ©pertoire de ce cpuset de plus haut niveau, sous le contrĂŽle de l’administrateur systĂšme. Des processus peuvent ĂȘtre placĂ©s dans ces autres cpusets.

Les cpusets sont intĂ©grĂ©s dans le noyau avec le mĂ©canisme d’affinitĂ© d’ordonnancement de sched_setaffinity (2) et les mĂ©canismes de placement en mĂ©moire de mbind (2) et set_mempolicy (2). Aucun de ces mĂ©canismes ne permettent Ă  un processus d’utiliser un CPU ou un nƓud mĂ©moire qui n’est pas autorisĂ© par le cpuset du processus. Si une modification du cpuset entre en conflit avec ces autres mĂ©canismes, le placement dans le cpuset est forcĂ©, mĂȘme si cela signifie qu’il faut outrepasser ces autres mĂ©canismes. Ceci est fait silencieusement par le noyau en restreignant les CPU et nƓuds mĂ©moire demandĂ©s par ces autres mĂ©canismes Ă  ceux qui sont autorisĂ©s par le cpuset du processus appelant. Ces autres appels peuvent alors renvoyer une erreur si, par exemple, ils sont amenĂ©s Ă  demander un ensemble vide de CPU ou de nƓuds mĂ©moire aprĂšs que la demande est restreinte au cpuset du processus appelant.

Typiquement, un cpuset est utilisĂ© pour gĂ©rer le confinement dans des CPU ou des nƓuds mĂ©moire pour un ensemble de processus qui coopĂšrent entre eux, comme un ordonnanceur de tĂąches, et ces autres mĂ©canismes permettent de gĂ©rer le placement de chacun des processus ou des rĂ©gions mĂ©moire pour chacune de ces tĂąches.

FICHIERS

Chaque rĂ©pertoire de /dev/cpuset reprĂ©sente un cpuset et contient un ensemble dĂ©finit de pseudofichiers qui dĂ©crivent l’état de ce cpuset.

Les nouveaux cpusets sont créés avec l’appel systĂšme mkdir (2) ou la commande mkdir (1). Les propriĂ©tĂ©s d’un cpuset, comme ses drapeaux, les CPU et nƓuds mĂ©moire autorisĂ©s et les processus attachĂ©s sont rĂ©cupĂ©rĂ©s ou modifiĂ©s en lisant ou Ă©crivant dans le fichier appropriĂ© du rĂ©pertoire du cpuset. Ces fichiers sont dĂ©crits ci-dessous.

Les pseudofichiers dans chaque rĂ©pertoire d’un cpuset sont créés automatiquement quand le cpuset est créé, suite Ă  l’appel Ă  mkdir (2). Il n’est pas possible d’ajouter ou de supprimer directement ces pseudofichiers.

Le rĂ©pertoire d’un cpuset qui ne contient pas de rĂ©pertoire pour un cpuset fils et n’a pas de processus lui Ă©tant attachĂ© peut ĂȘtre supprimĂ© Ă  l’aide de rmdir (2) ou rmdir (1). Il n’est pas nĂ©cessaire, ou possible, de supprimer les pseudofichiers du rĂ©pertoire avant de le supprimer.

Les pseudofichiers des rĂ©pertoires d’un cpuset sont de petits fichiers textes qui peuvent ĂȘtre lus ou Ă©crits en utilisant les outils traditionnels comme cat (1) et echo (1) ou depuis un programme en utilisant des fonctions d’une bibliothĂšque d’entrĂ©es sorties ou des appels systĂšme, comme open (2), read (2), write (2) et close (2).

Les pseudofichiers dans un rĂ©pertoire d’un cpuset reprĂ©sentent l’état interne du noyau et n’ont pas de reprĂ©sentation persistante sur le disque. Les fichiers d’un cpuset sont listĂ©s et dĂ©crits ci-dessous.

tasks

Liste des identifiants de processus (PID) des processus dans ce cpuset. La liste contient une sĂ©rie de nombres dĂ©cimaux au format ASCII, chacun suivit d’une nouvelle ligne. Un processus peut ĂȘtre ajoutĂ© Ă  un cpuset (ce qui le supprime automatiquement du cpuset qui le contenait auparavant) en Ă©crivant son PID dans le fichier tasks du cpuset (avec ou sans nouvelle ligne Ă  la fin).

Attention : un seul PID peut ĂȘtre Ă©crit Ă  la fois dans le fichier tasks . Si une chaĂźne est Ă©crite et qu’elle contient plus d’un PID, seul le premier sera utilisĂ©.

notify_on_release

Drapeau (0 ou 1). Lorsqu’il est activĂ© (1), ce cpuset sera gĂ©rĂ© de façon particuliĂšre une fois qu’il sera libĂ©rĂ©, c’est-Ă -dire aprĂšs que tous les processus cessent de l’utiliser (c’est-Ă -dire se terminent ou ont Ă©tĂ© dĂ©placĂ©s dans un autre ensemble de CPU) et que tous les rĂ©pertoires des cpusets fils ont Ă©tĂ© supprimĂ©s. Consultez la section Notification Ă  la libĂ©ration ci-dessous.

cpuset.cpus

Liste des numĂ©ros physiques des CPU sur lesquels les processus de ce cpuset ont le droit de s’exĂ©cuter. Consultez la section Format des listes ci-dessous pour une description du format de cpus .

Les CPU autorisĂ©s pour un cpuset peuvent ĂȘtre changĂ©s en Ă©crivant une nouvelle liste dans la fichier cpus .

cpuset.cpu_exclusive

Drapeau (0 ou 1). S’il est activĂ© (1), le cpuset a un accĂšs exclusif Ă  ses CPU (des cpusets frĂšres ou cousins ne peuvent pas partager de CPU). Par dĂ©faut, il est dĂ©sactivĂ© (0). Les cpusets nouvellement créés ont aussi ce drapeau de dĂ©sactivĂ© (0) au dĂ©but.

Deux cpusets sont frĂšres s’ils ont le mĂȘme cpuset pĂšre dans la hiĂ©rarchie /dev/cpuset . Deux cpusets sont cousins si aucun n’est l’ancĂȘtre de l’autre. IndĂ©pendamment du paramĂštre cpu_exclusive , si un cpuset est l’ancĂȘtre d’un autre et si ces deux cpusets ont des listes de CPU ( cpus ) non vides, alors leurs listes de CPU doivent se chevaucher parce que la liste cpus d’un cpuset est toujours un sous ensemble de la liste cpus de son cpuset pĂšre.

cpuset.mems

Liste des nƓuds mĂ©moire sur lesquels les processus de ce cpuset ont le droit d’allouer de la mĂ©moire. Consultez la section Format des listes ci-dessous pour une description du format de mems .

cpuset.mem_exclusive

Drapeau (0 ou 1). S’il est activĂ© (1), le cpuset a un accĂšs exclusif Ă  ses nƓuds mĂ©moire (pas de partage entre frĂšres ou cousins). S’il est activĂ© (1), il s’agit Ă©galement d’un cpuset « Hardwall » (voir ci-dessous). Par dĂ©faut, il est dĂ©sactivĂ© (0). Les cpusets nouvellement créés ont aussi ce drapeau de dĂ©sactivĂ© (0) au dĂ©but.

IndĂ©pendamment du paramĂštre mem_exclusive , si un cpuset est l’ancĂȘtre d’un autre, alors leurs nƓuds mĂ©moires doivent se chevaucher parce que l’ensemble des nƓuds mĂ©moire d’un cpuset est toujours un sous ensemble des nƓuds mĂ©moire du cpuset pĂšre.

cpuset.mem_hardwall (depuis Linux 2.6.26)

Drapeau (0 ou 1). S’il est activĂ© (1), le cpuset est de type Hardwall (voir ci-dessous). Contrairement Ă  mem_exclusive , des cpusets marquĂ©s avec mem_hardwall peuvent partager des nƓuds mĂ©moire avec des cpusets frĂšres ou cousins. Par dĂ©faut, il est dĂ©sactivĂ© (0). Les cpusets nouvellement créés ont aussi ce drapeau de dĂ©sactivĂ© (0) au dĂ©but.

cpuset.memory_migrate (depuis Linux 2.6.16)

Drapeau (0 ou 1). S’il est activĂ© (1), alors la migration mĂ©moire est activĂ©e. Par dĂ©faut, il est dĂ©sactivĂ© (0). Consultez la section Migration mĂ©moire ci-dessous.

cpuset.memory_pressure (depuis Linux 2.6.16)

Une mesure de la pression mĂ©moire causĂ©e par les processus d’un cpuset. Consultez la section Pression mĂ©moire ci-dessous. À moins que memory_pressure_enabled soit activĂ©, il vaut toujours zĂ©ro. Ce fichier est en lecture seule. Consultez la section AVERTISSEMENTS ci-dessous.

cpuset.memory_pressure_enabled (depuis Linux 2.6.16)

Drapeau (0 ou 1). Ce fichier n’est prĂ©sent que dans le cpuset racine, qui est normalement /dev/cpuset . S’il est activĂ© (1), les calculs de memory_pressure sont activĂ©s pour tous les cpusets du systĂšme. Par dĂ©faut, il est dĂ©sactivĂ© (0). Consultez la section Pression mĂ©moire ci-dessous.

cpuset.memory_spread_page (depuis Linux 2.6.17)

Drapeau (0 ou 1). S’il est activĂ© (1), les pages du cache de pages du noyau (les tampons des systĂšmes de fichiers) sont distribuĂ©es uniformĂ©ment dans les cpusets. Par dĂ©faut, il est dĂ©sactivĂ© (0) dans le cpuset racine et hĂ©ritĂ© du cpuset parent pour les cpusets nouvellement créés. Consultez la section RĂ©partition mĂ©moire ci-dessous.

cpuset.memory_spread_slab (depuis Linux 2.6.17)

Drapeau (0 ou 1). S’il est activĂ© (1), les caches slab (N.d.T. : tampons prĂ©allouĂ©s par le noyau) pour les entrĂ©es-sorties de fichiers (des structures pour des rĂ©pertoires ou inƓuds) sont rĂ©partis uniformĂ©ment dans le cpuset. Par dĂ©faut, ce drapeau est dĂ©sactivĂ© (0) dans le cpuset racine et les nouveaux cpusets hĂ©ritent du drapeau de leur parent quand ils sont créés. Consultez la section RĂ©partition mĂ©moire ci-dessous.

cpuset.sched_load_balance (depuis Linux 2.6.24)

Drapeau (0 ou 1). S’il est activĂ© (1, la valeur par dĂ©faut), le noyau rĂ©partira automatiquement la charge des processus du cpuset au travers les CPU autorisĂ©s pour le cpuset. S’il est dĂ©sactivĂ© (0), le noyau ne rĂ©partira pas la charge des processus du cpuset, Ă  moins qu’un autre cpuset qui partage des CPU avec lui n’ait son drapeau sched_load_balance activĂ©. Consultez la section RĂ©partition de la charge par l’ordonnanceur ci-dessous pour plus de dĂ©tails.

cpuset.sched_relax_domain_level (depuis Linux 2.6.26)

Entier, compris entre -1 et une petite valeur positive. sched_relax_domain_level contrĂŽle la largeur de l’intervalle des CPU pour lesquels le noyau effectue une rĂ©partition immĂ©diate des tĂąches exĂ©cutables. Si sched_load_balance est dĂ©sactivĂ©, alors sched_relax_domain_level ne compte pas, puisqu’il n’y a pas de rĂ©partition de la charge. Si sched_load_balance est activĂ©, alors plus sched_relax_domain_level est important, plus l’intervalle des CPU sur lesquels le noyau essaie de rĂ©partir la charge est important. Consultez la section Niveau du domaine de dĂ©tente de l’ordonnanceur ci-dessous pour plus de dĂ©tails.

En plus des pseudofichiers décrits ci-dessus, dans chaque répertoire de /dev/cpuset , chaque processus a un pseudofichier, /proc/ pid /cpuset , qui indique le chemin vers le répertoire du cpuset du processus, relativement à la racine du systÚme de fichiers cpuset.

Quatre lignes sont Ă©galement ajoutĂ©es dans le fichier /proc/ pid /status , fournissant pour chaque processus les champs : Cpus_allowed (sur quels CPU il peut ĂȘtre ordonnancĂ©) et Mems_allowed (sur quels nƓuds mĂ©moire de la mĂ©moire peut ĂȘtre allouĂ©e), avec l’ Affichage sous forme de masque et l’ Affichage sous forme de liste (voir ci-dessous). Voici un exemple :

Cpus_allowed: ffffffff,ffffffff,ffffffff,ffffffff
Cpus_allowed_list: 0-127
Mems_allowed: ffffffff,ffffffff
Mems_allowed_list: 0-63

Les champs « allowed » ont été ajoutés dans Linux 2.6.24 ; les champs « allowed_list » ont été ajoutés dans Linux 2.6.26.

CAPACITÉS ÉTENDUES

En plus de contrĂŽler quels CPU ( cpus ) et nƓuds mĂ©moire ( mems ) un processus Ă  le droit d’utiliser, les cpusets fournissent les fonctionnalitĂ©s Ă©tendues suivantes.

Ensembles de CPU exclusifs

Si un cpuset est marquĂ© avec cpu_exclusive ou mem_exclusive , aucun autre cpuset, autre que des ancĂȘtres ou descendants directs, peuvent partager des CPU ou des nƓuds mĂ©moire avec ce cpuset.

Un cpuset dont mem_exclusive est activĂ© restreint les allocations du noyau pour les pages des tampons de cache et autres donnĂ©es internes du noyau communĂ©ment partagĂ©es par le noyau au travers diffĂ©rents utilisateurs. Tous les cpusets, que mem_exclusive soit activĂ© ou non, restreignent l’allocation de mĂ©moire depuis l’espace utilisateur. Ceci permet de configurer un systĂšme de telle sorte que diffĂ©rentes tĂąches puissent partager des donnĂ©es du noyau, tout en isolant toutes les allocations en mode utilisateur des tĂąches dans leur propre cpuset. Pour ceci, il faut crĂ©er un gros cpuset, avec mem_exclusive activĂ©, pour contenir toutes les tĂąches, et crĂ©er des cpuset fils sans mem_exclusive pour chacune des tĂąches. Seule une petite partie de la mĂ©moire du noyau, comme les requĂȘtes des gestionnaires d’interruptions, est autorisĂ©e Ă  ĂȘtre placĂ©e sur des nƓuds mĂ©moire en dehors d’un cpuset, mĂȘme si mem_exclusive est activĂ©.

Hardwall

Un cpuset pour lequel mem_exclusive ou mem_hardwall est activĂ© est un cpuset hardwall . Un cpuset hardwall restreint les allocations mĂ©moire du noyau pour les pages, tampons et toutes autre donnĂ©es partagĂ©s frĂ©quemment par le noyau au travers diffĂ©rents utilisateurs. Tous les cpusets, hardwall ou non, restreignent les allocations mĂ©moire pour l’espace utilisateur.

Ceci permet de configurer un systĂšme de telle sorte que diffĂ©rentes tĂąches indĂ©pendantes puissent partager des donnĂ©es du noyau, comme des pages des systĂšmes de fichiers, tout en isolant les allocations de l’espace utilisateur de chaque tĂąche dans leur cpuset. Pour ceci, il faut crĂ©er un gros cpuset hardwall qui contiendra toutes les tĂąches et crĂ©er des cpusets fils (non hardwall ) pour chacune des tĂąches.

Seule une petite quantitĂ© de mĂ©moire noyau, comme les demandes des gestionnaires d’interruption, peut ĂȘtre utilisĂ©e Ă  l’extĂ©rieur d’un cpuset hardwall .

Notification à la libération

Si le drapeau notify_on_release d’un cpuset est activĂ© (1), alors quand le dernier processus quitte le cpuset (il se termine ou s’attache Ă  un autre cpuset) et que le dernier cpuset fils de ce cpuset a Ă©tĂ© supprimĂ©, le noyau exĂ©cutera la commande /sbin/cpuset_release_agent en lui fournissant le chemin (relatif au point de montage du systĂšme de fichiers cpuset) du cpuset abandonnĂ©. Ceci permet de supprimer automatiquement les cpusets abandonnĂ©s.

Le drapeau notify_on_release du cpuset racine est désactivé (0) par défaut au moment du démarrage. La valeur par défaut pour les autres cpusets lors de leur création est égale à la valeur de notify_on_release de leur cpuset parent.

La commande /sbin/cpuset_release_agent est appelée, avec dans argv[1] le nom (un chemin relatif à /dev/cpuset ) du cpuset à supprimer.

Le contenu habituel de la commande /sbin/cpuset_release_agent est simplement le script shell suivant :

#!/bin/sh
rmdir /dev/cpuset/$1

Comme pour les autres drapeaux ci-dessous, ce drapeau peut ĂȘtre modifiĂ© en Ă©crivant un 0 ou un 1 ASCII (avec ou sans fin de ligne) dans le fichier pour respectivement dĂ©sactiver ou activer le drapeau.

Pression mémoire

Le fichier memory_pressure d’un cpuset indique la moyenne instantanĂ©e du taux auquel les processus du cpuset tentent de libĂ©rer de la mĂ©moire utilisĂ©e sur les nƓuds du cpuset pour satisfaire les nouvelles demandes de mĂ©moire.

Ceci permet Ă  un gestionnaire de tĂąches de superviser les tĂąches qui s’exĂ©cutent dans des cpuset dĂ©diĂ©s et dĂ©tecter efficacement la pression mĂ©moire qu’une tĂąche produit.

Ceci est utile Ă  la fois pour les systĂšmes trĂšs surveillĂ©s qui exĂ©cutent diverses tĂąches qui leurs sont fournies et peuvent choisir de terminer ou de changer la prioritĂ© des tĂąches qui essaient d’utiliser plus de mĂ©moire que les nƓuds mĂ©moire qui leurs ont Ă©tĂ© assignĂ©s leurs permettent, et les systĂšmes pour du calcul scientifique avec des tĂąches parallĂšles, fortement couplĂ©es, au temps d’exĂ©cution important, qui ne pourraient plus fournir les performances demandĂ©es si elles se mettaient Ă  utiliser plus de mĂ©moire qu’elles n’en ont droit.

Ce mĂ©canisme fourni un moyen trĂšs Ă©conomique pour dĂ©tecter des signes de pression mĂ©moire sur un cpuset. L’action Ă  effectuer lorsqu’un signe de pression mĂ©moire est dĂ©tectĂ© est laissĂ© au libre arbitre du gestionnaire des tĂąches ou autre code utilisateur.

À moins que le calcul de la pression mĂ©moire soit activĂ© par le pseudofichier /dev/cpuset/cpuset.memory_pressure_enabled , cette pression mĂ©moire n’est calculĂ©e pour aucun cpuset et les lectures dans les fichiers memory_pressure renvoient toujours zĂ©ro, c’est-Ă -dire la chaĂźne ASCII « 0\en ». Consultez la section AVERTISSEMENTS ci-dessous.

Une moyenne instantanée par cpuset est utilisée pour les raisons suivantes :

-

Comme cette mĂ©trique est par cpuset plutĂŽt que par processus ou par rĂ©gion mĂ©moire virtuelle, la charge du systĂšme due Ă  la supervision de cette mĂ©trique par un ordonnanceur de tĂąches est fortement rĂ©duite sur les gros systĂšmes, Ă©tant donnĂ© qu’il n’est pas nĂ©cessaire de parcourir la liste des tĂąches Ă  chaque fois.

-

Comme cette mĂ©trique est une moyenne instantanĂ©e plutĂŽt qu’un compteur, un ordonnanceur de tĂąches obtient la pression mĂ©moire en une seule lecture sans avoir Ă  lire et se souvenir des rĂ©sultats pendant un certain temps.

-

Comme cette mĂ©trique est par cpuset plutĂŽt que par processus, l’ordonnanceur de tĂąches peut obtenir l’information importante, la pression mĂ©moire dans un cpuset, en une seule lecture sans nĂ©cessiter d’obtenir et de se souvenir des rĂ©sultats pour tous les processus d’un cpuset (la liste des processus peut changer dynamiquement).

La pression mĂ©moire d’un cpuset est calculĂ©e en utilisant un simple filtre digital par cpuset dans le noyau. Pour chaque cpuset, ce filtre suit le taux auquel les processus attachĂ©s Ă  ce cpuset demandent au noyau de rĂ©utiliser de la mĂ©moire.

Ces demandes de rĂ©utilisation de mĂ©moire se produisent quand un processus doit satisfaire une demande de page mĂ©moire en trouvant d’abord une page Ă  rĂ©utiliser, du fait de l’absence de page disponible dĂ©jĂ  prĂȘte. Les pages sales des systĂšmes de fichiers sont rĂ©utilisĂ©es en les Ă©crivant d’abord sur le disque. Les tampons des systĂšmes de fichiers qui n’ont pas Ă©tĂ© modifiĂ©s sont rĂ©utilisĂ©s tout simplement en les abandonnant, mais si cette page est nĂ©cessaire de nouveau, il faudra la relire sur le disque.

Le fichier cpuset.memory_pressure fournit un nombre entier qui reprĂ©sente le taux des demandes rĂ©centes (la demi-vie est de 10 secondes) de rĂ©utilisation de mĂ©moire par les processus du cpuset, l’unitĂ© Ă©tant le nombre de demandes par seconde fois 1000.

Répartition mémoire

Il y a deux fichiers, par cpuset, pour des drapeaux boolĂ©ens qui contrĂŽlent oĂč le noyau alloue les pages pour les tampons des systĂšmes de fichiers et les structures de donnĂ©es liĂ©es internes au noyau. Ces fichiers sont cpuset.memory_spread_page et cpuset.memory_spread_slab .

Si le drapeau boolĂ©en cpuset.memory_spread_page est activĂ©, alors le noyau rĂ©partit les tampons des systĂšmes de fichiers (les caches des pages) Ă©quitablement sur tous les nƓuds autorisĂ©s pour le processus qui demande la page, au lieu de placer ces pages de prĂ©fĂ©rence sur le nƓud sur lequel s’exĂ©cute le processus.

Si le drapeau boolĂ©en cpuset.memory_spread_slab d’un cpuset est activĂ©, alors le noyau rĂ©partira uniformĂ©ment les caches slab liĂ©s aux systĂšmes de fichiers, comme ceux pour des entrĂ©es d’inƓuds ou de rĂ©pertoires, sur tous les nƓuds autorisĂ©s pour le processus qui demande de la mĂ©moire, plutĂŽt que de prĂ©fĂ©rer mettre ces pages sur le nƓud sur lequel s’exĂ©cute le processus.

La configuration de ces drapeaux n’affecte pas les pages du segment de donnĂ©es (consultez brk (2)) ou du segment de la pile d’un processus.

Par dĂ©faut, les deux types de rĂ©partition de la mĂ©moire sont dĂ©sactivĂ©s et le noyau prĂ©fĂšre allouer la mĂ©moire sur le nƓud local oĂč s’exĂ©cute le processus. Si ce nƓud n’est pas autorisĂ© par la politique NUMA du processus ou par la configuration des cpusets ou s’il n’y a plus suffisamment de pages mĂ©moire disponibles sur ce nƓud, alors le noyau recherche le nƓud le plus proche Ă©tant autorisĂ© et ayant suffisamment de pages disponibles.

Quand un nouveau cpuset est créé, il hérite de la configuration de répartition mémoire de son pÚre.

Activer la rĂ©partition mĂ©moire a pour effet d’ignorer la politique mĂ©moire NUMA du processus pour les allocations de pages ou de caches slab, qui sont alors Ă©parpillĂ©es. Cependant, les changements dus Ă  la rĂ©partition mĂ©moire demandĂ©e par un cpuset ne sont pas visibles pour les appels systĂšme mbind (2) ou set_mempolicy (2). Ces deux appels systĂšme liĂ©s Ă  la politique mĂ©moire NUMA semblent se comporter comme si aucune rĂ©partition mĂ©moire n’était demandĂ©e par un cpuset, mĂȘme si c’est le cas. Si la rĂ©partition mĂ©moire est par la suite dĂ©sactivĂ©e pour les cpuset, la derniĂšre politique mĂ©moire NUMA dĂ©finie par ces appels est automatiquement appliquĂ©e de nouveau.

cpuset.memory_spread_page et cpuset.memory_spread_slab sont tous les deux des fichiers contenant des drapeaux booléens. Par défaut, ils contiennent un « 0 », ce qui signifie que la fonctionnalité est désactivée pour ce cpuset. Si un « 1 » est écrit dans le fichier, la fonctionnalité correspondante est activée.

La rĂ©partition mĂ©moire d’un cpuset se comporte de façon similaire Ă  ce qui est connu (dans d’autres contextes) comme le placement mĂ©moire Ă  tour de rĂŽle (« round-robin ») ou entrelacĂ© (« interleave »).

La configuration d’une stratĂ©gie de rĂ©partition mĂ©moire pour un cpuset peut amĂ©liorer significativement les performances pour les tĂąches qui :

-

nĂ©cessitent de placer les donnĂ©es locales des threads dans des nƓuds mĂ©moire proches des CPU qui exĂ©cutent les threads qui accĂšdent le plus frĂ©quemment Ă  ces donnĂ©es ; mais aussi

-

nĂ©cessitent d’accĂ©der Ă  de gros ensembles de donnĂ©es de systĂšmes de fichiers qui doivent ĂȘtre rĂ©partis sur diffĂ©rents nƓuds du cpuset de la tĂąche du fait de leurs tailles.

Sans cette politique, la rĂ©partition des allocations mĂ©moire sur les nƓuds du cpuset de la tĂąche peut ne pas ĂȘtre Ă©quitable, particuliĂšrement pour les tĂąches qui n’auraient qu’un thread chargĂ© de l’initialisation ou de la lecture des donnĂ©es d’entrĂ©e.

Migration mémoire

Normalement, avec la configuration de cpuset.memory_migrate par dĂ©faut (dĂ©sactivĂ©), une fois qu’une page est allouĂ©e (une page physique de la mĂ©moire lui est donnĂ©e), cette page reste sur le nƓud oĂč elle a Ă©tĂ© allouĂ©e, tant qu’elle reste allouĂ©e, mĂȘme si la politique de placement mĂ©moire du cpuset ( mems ) change par la suite.

Quand la migration mĂ©moire est activĂ©e pour un cpuset, si la configuration de mems est modifiĂ©e alors toute page mĂ©moire utilisĂ©e par un processus du cpuset qui se trouverait sur un nƓud mĂ©moire qui n’est plus autorisĂ© sera dĂ©placĂ©e sur un nƓud mĂ©moire qui est autorisĂ©.

De plus, si un processus est dĂ©placĂ© dans un cpuset dont le drapeau memory_migrate est activĂ©, toutes les pages mĂ©moire qu’il utilise et qui se trouvent sur des nƓuds mĂ©moire qui Ă©taient autorisĂ©s dans son cpuset prĂ©cĂ©dant mais ne le sont plus dans le nouveau cpuset seront dĂ©placĂ©es sur un nƓud mĂ©moire autorisĂ© pour le nouveau cpuset.

L’emplacement relatif d’un page dĂ©placĂ©e d’un cpuset est prĂ©servĂ© si possible lors de ces opĂ©rations de dĂ©placement. Par exemple, si la page se trouvait sur le deuxiĂšme nƓud valable du prĂ©cĂ©dent cpuset, alors la page sera placĂ©e sur le deuxiĂšme nƓud valable du nouveau cpuset, si c’est possible.

RĂ©partition de la charge par l’ordonnanceur

L’ordonnanceur du noyau rĂ©partit automatiquement la charge des processus. Si un CPU est sous-utilisĂ©, le noyau recherchera des processus sur d’autres CPU plus chargĂ©s et dĂ©placera ces processus sur le CPU sous-utilisĂ© Ă  condition que les mĂ©canismes comme les cpuset et sched_setaffinity (2) le permettent.

Le coĂ»t de l’algorithme de rĂ©partition de la charge et son impact sur les structures de donnĂ©es partagĂ©es du noyau, comme la liste des processus, augmente plus que linĂ©airement avec le nombre de CPU qui interviennent pour la rĂ©partition de la charge. Par exemple le coĂ»t pour la rĂ©partition de la charge dans un grand ensemble de CPU sera supĂ©rieur Ă  celui pour la rĂ©partition de la charge dans deux ensembles ayant moitiĂ© moins de CPU. (La relation entre le nombre de CPU intervenant dans la rĂ©partition de la charge et le coĂ»t de cette rĂ©partition de charge dĂ©pend de l’implĂ©mentation de l’ordonnanceur de processus du noyau, qui change dans le temps quand de meilleurs algorithmes d’ordonnancement sont implĂ©mentĂ©s)

Le drapeau sched_load_balance d’un cpuset permet de supprimer cette rĂ©partition automatique de la charge dans les cas oĂč elle n’est pas nĂ©cessaire et que sa suppression amĂ©liorerait les performances.

Par dĂ©faut, la rĂ©partition de la charge se fait sur tous les CPU, Ă  l’exception de ceux marquĂ©s comme Ă©tant isolĂ©s en utilisant au moment du dĂ©marrage le paramĂštre du noyau « isolcpus= ». (Consultez la section Niveau du domaine de dĂ©tente de l’ordonnanceur ci-dessous pour changer le comportement par dĂ©faut)

Cette rĂ©partition de la charge par dĂ©faut n’est pas bien adaptĂ©e aux situations suivantes :

-

Sur les gros systĂšmes, la rĂ©partition de la charge sur beaucoup de CPU est trĂšs coĂ»teuse. Si le systĂšme est gĂ©rĂ© avec des cpusets pour placer les tĂąches indĂ©pendantes sur diffĂ©rents ensembles de CPU, une rĂ©partition de la charge complĂšte n’est pas nĂ©cessaire.

-

Les systĂšmes avec une prise en charge temps-rĂ©el sur certains CPU doivent minimiser la surcharge du systĂšme sur ces CPU et donc Ă©viter la rĂ©partition de la charge des processus si elle n’est pas nĂ©cessaire.

Quand le drapeau sched_load_balance d’un cpuset est activĂ© (ce qui est le cas par dĂ©faut), une rĂ©partition de la charge sur tous les CPU autorisĂ©s par le cpuset est demandĂ©, Ă  condition que le processus puisse ĂȘtre dĂ©placĂ© d’un CPU du cpuset Ă  un autre CPU (c’est-Ă -dire qu’il n’ait pas Ă©tĂ© attachĂ© Ă  des CPU avec, par exemple, sched_setaffinity (2)).

Quand le drapeau sched_load_balance d’un cpuset est dĂ©sactivĂ©, alors l’ordonnanceur Ă©vitera de dĂ©placer des processus pour rĂ©partir la charge des CPU du cpuset, sauf si un autre cpuset partage le mĂȘme CPU et a son drapeau sched_load_balance activĂ©.

Ainsi, par exemple, si le cpuset racine a son drapeau sched_load_balance activĂ©, alors l’ordonnanceur rĂ©partira la charge sur tous les CPU et la configuration du drapeau sched_load_balance des autres cpusets n’a pas d’effet, puisqu’une rĂ©partition complĂšte de la charge est dĂ©jĂ  demandĂ©e.

Dans les deux situations ci-dessus, le drapeau sched_load_balance devrait donc ĂȘtre dĂ©sactivĂ© sur le cpuset racine et seuls les cpusets fils plus petits devraient l’activer.

Lorsque vous faites ceci, vous ne devez gĂ©nĂ©ralement pas laisser un processus non attachĂ© Ă  un CPU dans le cpuset racine qui pourrait utiliser les CPU de façon non nĂ©gligeable. De cette façon les processus peuvent ĂȘtre artificiellement contraints Ă  un sous ensemble des CPU en fonction de la configuration de ce drapeau dans les cpusets descendants. MĂȘme si ce processus pourrait utiliser des cycles CPU inutilisĂ©s par certains CPU, l’ordonnanceur du noyau ne cherchera pas Ă  rĂ©partir la charge du processus sur le CPU sous utilisĂ©.

Bien sĂ»r, les processus attachĂ©s Ă  un CPU particulier peuvent ĂȘtre laissĂ©s dans un cpuset qui dĂ©sactive sched_load_balance puisque ces processus ne peuvent ĂȘtre dĂ©placĂ©s de toute façon.

Niveau du domaine de dĂ©tente de l’ordonnanceur

L’ordonnanceur du noyau effectue une rĂ©partition de la charge immĂ©diate lorsqu’un CPU devient disponible ou lorsqu’une autre tĂąche est prĂȘte. Cette rĂ©partition de la charge permet de s’assurer que le plus de CPU possibles sont utilisĂ©s efficacement en exĂ©cutant des tĂąches. Le noyau effectue aussi une rĂ©partition de la charge de façon plus sporadique sur la base de l’horloge logicielle dĂ©crite dans time (7). La configuration de sched_relax_domain_level ne s’applique qu’à la rĂ©partition de charge automatique. IndĂ©pendamment de la configuration de sched_relax_domain_level , une rĂ©partition de charge sporadique est effectuĂ©e Ă  travers tous les CPU (sauf si cela a Ă©tĂ© dĂ©sactivĂ© avec sched_load_balance ). Dans tous les cas, bien sĂ»r, les tĂąches ne seront exĂ©cutĂ©es que sur les CPU autorisĂ©s par leur cpuset et par les appels systĂšmes sched_setaffinity (2).

Sur les petits systĂšmes, avec peu de CPU, la rĂ©partition de charge immĂ©diate est utile pour amĂ©liorer l’interactivitĂ© du systĂšme et minimiser les cycles CPU inutilisĂ©s. Mais sur les gros systĂšmes, essayer de rĂ©partir la charge immĂ©diatement sur un nombre important de CPU peut ĂȘtre plus coĂ»teux que ce que ça ne rapporte, en fonction des performances des diffĂ©rentes tĂąches et du matĂ©riel.

La signification exacte des petites valeurs de sched_relax_domain_level dĂ©pendra de l’implĂ©mentation de l’ordonnanceur du noyau et de l’architecture non uniforme du matĂ©riel. Ces deux paramĂštres Ă©volueront dans le temps et dĂ©pendent de l’architecture du systĂšme et de la version du noyau.

À ce jour, quand cette capacitĂ© a Ă©tĂ© introduite sous Linux 2.6.26, la signification des valeurs positives de sched_relax_domain_level est la suivante pour certaines des architectures les plus courantes :

1

Effectuer immĂ©diatement une rĂ©partition de la charge sur les diffĂ©rents Hyper-Thread frĂšres d’un mĂȘme cƓur.

2

Effectuer immĂ©diatement une rĂ©partition de la charge sur les diffĂ©rents cƓurs d’un processeur.

3

Effectuer immĂ©diatement une rĂ©partition de la charge sur les diffĂ©rents CPU d’un mĂȘme nƓud ou d’une mĂȘme lame.

4

Effectuer immĂ©diatement une rĂ©partition de la charge sur les diffĂ©rents (dĂ©tail d’implĂ©mentation) nƓuds [pour les systĂšmes NUMA].

5

Effectuer immĂ©diatement une rĂ©partition de la charge sur tous les CPU d’un systĂšme [pour les systĂšmes NUMA].

La valeur zĂ©ro (0) pour sched_relax_domain_level signifie toujours qu’il n’y a pas de rĂ©partition de charge immĂ©diate, et donc la rĂ©partition de la charge s’effectue pĂ©riodiquement et non pas immĂ©diatement quand un CPU devient disponible ou qu’une tĂąche peut ĂȘtre exĂ©cutĂ©e.

La valeur -1 pour sched_relax_domain_level signifie toujours qu’il faut utiliser la valeur par dĂ©faut du systĂšme. La valeur par dĂ©faut du systĂšme peut varier en fonction de l’architecture et du noyau. Cette valeur par dĂ©faut du systĂšme peut ĂȘtre modifiĂ©e en fournissant au noyau un paramĂštre « relax_domain_level= » lors du dĂ©marrage.

Si des cpusets partagent des CPU et ont des valeurs de sched_relax_domain_level incompatibles, alors la valeur la plus Ă©levĂ©e s’applique Ă  tous les CPU de ces cpusets. Dans ce cas, -1 est la valeur la plus faible, remplacĂ©e par toute autre valeur et -0 est la valeur la plus faible suivante.

FORMATS

Les formats suivants sont utilisĂ©s pour reprĂ©senter des ensembles de CPU et de nƓuds mĂ©moire.

Affichage sous forme de masque

L’ Affichage sous forme de masque est utilisĂ© pour reprĂ©senter les masques de bits des CPU et nƓuds mĂ©moire dans le fichier /proc/ pid /status .

Ce format affiche chaque mot de 32 bits au format hexadĂ©cimal (en utilisant les caractĂšres ASCII « 0 » - « 9 » et « a » - « f ») ; le dĂ©but des mots est complĂ©tĂ© par des zĂ©ros si nĂ©cessaire. Pour les masques de plus d’un mot, une virgule est utilisĂ©e pour sĂ©parer les mots. Les mots sont affichĂ© au format grand boutiste, avec le bit le plus significatif en premier. Les chiffres hexadĂ©cimaux d’un mot utilise aussi l’ordre grand boutiste.

Le nombre de mots de 32 bits affichés est le nombre minimal nécessaire pour afficher tous les bits du masque, en fonction de la taille du masque de bits.

Exemple d’ Affichage sous forme de masque :

00000001 # seul le bit 0
40000000,00000000,00000000 # seul le bit 94
00000001,00000000,00000000 # seul le bit 64
000000ff,00000000 # seuls les bits 32-39
00000000,000e3862 # les bits 1,5,6,11-13,17-19

Un masque avec les bits 0, 1, 2, 4, 8, 16, 32 et 64 activés sera affiché de cette façon :

00000001,00000001,00010117

Le premier « 1 » correspond au bit 64, le second au bit 32, le troisiÚme au bit 16, le quatriÚme au bit 8, le cinquiÚme au bit 4 et le « 7 » correspond aux bits 2, 1 et 0.

Affichage sous forme de liste

L’ Affichage sous forme de liste pour les fichiers cpus et mems est une liste de numĂ©ros ou intervalles de CPU ou de nƓuds mĂ©moire sĂ©parĂ©s par des virgules, en dĂ©cimal au format ASCII.

Exemple d’ Affichage sous forme de liste :

0-4,9 # bits 0, 1, 2, 3, 4 et 9 activés
0-2,7,12-14 # bits 0, 1, 2, 7, 12, 13 et 14 activés

RÈGLES

Les rùgles suivantes s’appliquent à chaque cpuset :

-

Ses CPU et nƓuds mĂ©moire doivent ĂȘtre des sous-ensembles de ceux de leur parent (ou les mĂȘmes ensembles).

-

Il ne peut ĂȘtre marquĂ© avec cpu_exclusive que si son parent l’est.

-

Il ne peut ĂȘtre marquĂ© avec mem_exclusive que si son parent l’est.

-

S’il est marquĂ© avec cpu_exclusive , ses CPU ne doivent pas ĂȘtre partagĂ©s avec ses frĂšres.

-

S’il est marquĂ© avec mem_exclusive , ses nƓuds mĂ©moire ne doivent pas ĂȘtre partagĂ©s avec ses frĂšres.

PERMISSIONS

Les permissions d’un cpuset sont dĂ©terminĂ©es par les permissions des rĂ©pertoires et pseudofichiers du systĂšme de fichiers cpuset, normalement montĂ© dans /dev/cpuset .

Par exemple, un processus peut se placer dans un autre cpuset s’il peut Ă©crire dans le fichier tasks de ce cpuset. Ceci nĂ©cessite les permission d’exĂ©cution des rĂ©pertoires Ă  traverser et la permission d’écrire dans le fichier tasks .

Une contrainte supplĂ©mentaire s’applique aux demandes de dĂ©placement d’autres processus dans un cpuset. Un processus ne peut pas attacher un autre processus Ă  un cpuset Ă  moins qu’il ait la permission d’envoyer un signal Ă  ce processus (consultez kill (2)).

Un processus peut crĂ©er un cpuset fils s’il a accĂšs et peut Ă©crire dans le rĂ©pertoire du cpuset pĂšre. Il peut modifier les CPU et nƓuds mĂ©moire d’un cpuset s’il a accĂšs au rĂ©pertoire de ce cpuset (les permissions d’exĂ©cuter tous les rĂ©pertoires parents) et s’il peut Ă©crire dans les fichiers correspondants cpus ou mems .

Il y a une petite diffĂ©rence entre la maniĂšre dont ces permissions sont Ă©valuĂ©es et la maniĂšre dont sont Ă©valuĂ©es les permissions pour les opĂ©rations sur des systĂšmes de fichiers normaux. Le noyau interprĂšte les chemins relatifs en fonction du rĂ©pertoire de travail actuel d’un processus. MĂȘme quand on opĂšre sur un fichier d’un cpuset, les chemins relatifs sont interprĂ©tĂ©s en fonction du rĂ©pertoire de travail du processus, et non pas relativement au cpuset actuel du processus. Les seules façons pour que les chemins de cpusets soient interprĂ©tĂ©s relativement au cpuset actuel du processus sont soit que le processus utilise le rĂ©pertoire du cpuset comme rĂ©pertoire de travail (il a d’abord effectuĂ© un cd ou chdir (2) dans le rĂ©pertoire de son cpuset dans /dev/cpuset , ce qui est plutĂŽt inhabituel), soit que du code utilisateur convertit le chemin relatif au cpuset en un chemin absolu.

En thĂ©orie, ceci signifie que le code utilisateur devrait indiquer les cpusets en utilisant des chemins absolus, ce qui nĂ©cessite de connaĂźtre le point de montage du systĂšme de fichier cpuset (d’habitude, mais sans que ce soit nĂ©cessaire, /dev/cpuset ). En pratique, Ă  la connaissance de l’auteur, tous les utilitaires en mode utilisateur supposent que si le systĂšme de fichier cpuset est montĂ©, alors il est montĂ© dans /dev/cpuset . De plus, une pratique assez courante utilisĂ© pour du code Ă©crit soigneusement consiste Ă  vĂ©rifier la prĂ©sence du pseudofichier /dev/cpuset/tasks afin de vĂ©rifier que le pseudosystĂšme de fichiers cpuset est bien montĂ©.

AVERTISSEMENTS

Activation de memory_pressure

Par dĂ©faut, le fichier cpuset.memory_pressure d’un cpuset vaut zĂ©ro (0). À moins que cette fonctionnalitĂ© soit activĂ©e en Ă©crivant « 1 » dans le pseudofichier /dev/cpuset/cpuset.memory_pressure_enabled , le noyau ne calcule pas les valeurs des fichiers memory_pressure de chaque cpuset.

Utilisation de la commande echo

Lorsque la commande echo est utilisĂ©e dans un interprĂ©teur de commandes pour changer les valeurs des fichiers d’un cpuset, soyez conscient que la commande echo interne Ă  certains interprĂ©teurs de commandes n’affiche pas de message d’erreur si l’appel systĂšme write (2) Ă©choue. Par exemple, si la commande :

echo 19 > cpuset.mems

Ă©choue parce que le nƓud mĂ©moire numĂ©ro 19 n’est pas autorisĂ© (par exemple le systĂšme n’a pas de nƓud mĂ©moire numĂ©ro 19), alors la commande echo peut n’afficher aucune erreur. If faut mieux utiliser la commande externe /bin/echo pour changer la configuration d’un fichier d’un cpuset puisque cette commande affichera les erreurs de write (2), comme par exemple :

/bin/echo 19 > cpuset.mems
/bin/echo : erreur d’écriture : argument invalide

EXCEPTIONS

Placement mémoire

Les contraintes des cpusets ne s’appliquent pas Ă  toutes les allocations de mĂ©moire systĂšme pour les raisons suivantes :

Si la fonctionnalitĂ© de connexion Ă  chaud est utilisĂ©e pour supprimer tous les CPU d’un cpuset, alors le noyau mettra Ă  jour automatiquement la liste de CPU autorisĂ©s ( cpus_allowed ) de tous les processus attachĂ©s aux CPU du cpuset et autorisera tous les CPU. Le comportement est similaire lorsque la fonctionnalitĂ© de connexion Ă  chaud est utilisĂ©e pour la mĂ©moire. En gĂ©nĂ©ral, le noyau prĂ©fĂšre ne pas tenir compte du placement sur les CPU ou les nƓuds mĂ©moire plutĂŽt que d’abandonner un processus dont tous les CPU ou nƓuds mĂ©moire autorisĂ©s sont dĂ©connectĂ©s. Le code utilisateur devrait reconfigurer les cpusets pour ne mentionner que les CPU et les nƓuds mĂ©moire en ligne lorsque la fonctionnalitĂ© de connexion Ă  chaud est utilisĂ©e pour ajouter ou retirer ces ressources.

Quelques demandes d’allocation mĂ©moire critiques et internes au noyau, marquĂ©es GFP_ATOMIC, doivent ĂȘtre satisfaites immĂ©diatement. Le noyau peut rater des demandes ou ne pas fonctionner correctement si certaines de ces allocations Ă©chouent. Si une de ces demandes ne peut ĂȘtre satisfaite par le cpuset du processus en cours, alors les contraintes du cpuset sont relĂąchĂ©es et le noyau recherche de la mĂ©moire lĂ  oĂč il peut en trouver. Il est prĂ©fĂ©rable de ne pas respecter un cpuset plutĂŽt que de stresser le noyau.

Les allocations de mĂ©moire demandĂ©es par des pilotes du noyau lors du traitement d’une interruption ne se trouvent dans le contexte d’aucun processus et ne sont donc pas contraintes par les cpusets.

Renommer des cpusets

Vous pouvez utiliser l’appel systĂšme rename (2) pour renommer des cpusets. Seuls des renommages simples sont pris en charge ; c’est-Ă -dire que changer le nom du rĂ©pertoire d’un cpuset est autorisĂ©, mais dĂ©placer le rĂ©pertoire d’un cpuset dans un autre rĂ©pertoire n’est pas autorisĂ©.

ERREURS

L’implĂ©mentation des cpusets du noyau Linux positionne errno pour indiquer la raison de l’échec d’un appel systĂšme liĂ© Ă  un cpuset.

Les valeurs possible pour errno et leurs significations, lors d’un Ă©chec d’un appel systĂšme liĂ© Ă  un cpuset sont listĂ©es ci-dessous :

E2BIG

Tentative d’écriture ( write (2)) dans un fichier spĂ©cial d’un cpuset avec une longueur supĂ©rieure Ă  la longueur autorisĂ©e par le noyau pour ces Ă©critures.

EACCES

Tentative d’écriture ( write (2)) d’un identifiant de processus (PID) dans le fichier tasks d’un cpuset alors que l’appelant n’est pas autorisĂ© Ă  dĂ©placer le processus.

EACCES

Tentative d’ajout, avec write (2), d’un CPU ou d’un nƓud mĂ©moire dans un cpuset alors que ce CPU ou ce nƓud mĂ©moire ne se trouve pas dans le cpuset parent.

EACCES

Tentative d’activation, avec write (2), de cpuset.cpu_exclusive ou de cpuset.mem_exclusive sur un cpuset dont le parent n’a pas ces propriĂ©tĂ©s.

EACCES

Tentative d’écriture ( write (2)) dans un fichier cpuset.memory_pressure .

EACCES

Tentative de crĂ©ation d’un fichier dans le rĂ©pertoire d’un cpuset.

EBUSY

Tentative de suppression, avec rmdir (2), d’un cpuset auquel sont attachĂ©s des processus.

EBUSY

Tentative de suppression, avec rmdir (2), d’un cpuset ayant des ensembles de CPU fils.

EBUSY

Tentative de suppression d’un CPU ou d’un nƓud mĂ©moire d’un cpuset alors que le CPU ou le nƓud mĂ©moire se trouve Ă©galement dans un des fils du cpuset.

EEXIST

Tentative de crĂ©ation, avec mkdir (2), d’un cpuset qui existe dĂ©jĂ .

EEXIST

Tentative de renommage ( rename (2)) d’un cpuset avec un nom dĂ©jĂ  utilisĂ©.

EFAULT

Tentative de lecture ( read (2)) ou d’écriture ( write (2)) dans un fichier d’un cpuset en utilisant un tampon en dehors de l’espace mĂ©moire accessible par le processus appelant.

EINVAL

Tentative de modification d’un cpuset, en utilisant write (2), de telle sorte que les attributs cpu_exclusive ou mem_exclusive ne soient plus respectĂ©s pour ce cpuset ou ses frĂšres.

EINVAL

Tentative d’écriture (avec write (2)) d’une liste vide dans cpuset.cpus ou cpuset.mems pour un cpuset auquel sont dĂ©jĂ  attachĂ©s des processus ou des cpuset fils.

EINVAL

Tentative d’écriture (avec write (2)) dans cpuset.cpus ou cpuset.mems d’une liste qui comprend un intervalle dont la borne supĂ©rieure est infĂ©rieure Ă  la borne infĂ©rieure.

EINVAL

Tentative d’écriture (avec write (2)) dans cpuset.cpus ou cpuset.mems d’une liste dont la chaĂźne comprend un caractĂšre non valable.

EINVAL

Tentative d’écriture (avec write (2)) dans le fichier cpuset.cpus d’une liste qui ne comprend aucun CPU en ligne.

EINVAL

Tentative d’écriture (avec write (2)) dans le fichier cpuset.mems d’une liste qui ne comprend aucun nƓud mĂ©moire en ligne.

EINVAL

Tentative d’écriture (avec write (2)) dans le fichier cpuset.mems d’une liste qui comprend un nƓud qui ne contient pas de mĂ©moire.

EIO

Tentative d’écriture (avec write (2)) dans le fichier tasks d’un cpuset d’une chaĂźne qui ne commence pas par un entier dĂ©cimal au format ASCII.

EIO

Tentative de renommage (avec rename (2)) d’un cpuset dans un autre rĂ©pertoire.

ENAMETOOLONG

Tentative de lecture (avec read (2)) du fichier /proc/ pid /cpuset d’un cpuset, pour lequel le chemin est plus long que la taille des pages du noyau.

ENAMETOOLONG

Tentative de crĂ©ation, avec mkdir (2), d’un cpuset dont le nom du rĂ©pertoire de base fait plus de 255 caractĂšres.

ENAMETOOLONG

Tentative de crĂ©ation, avec mkdir (2), d’un cpuset dont le chemin complet, prĂ©fixe du point de montage compris (typiquement « /dev/cpuset/ »), fait plus de 4095 caractĂšres.

ENODEV

Le cpuset a Ă©tĂ© supprimĂ© par un autre processus en mĂȘme temps qu’une tentative d’écriture (avec write (2)) sur un des pseudofichiers du rĂ©pertoire du cpuset.

ENOENT

Tentative de crĂ©ation, avec mkdir (2), d’un cpuset dans un cpuset parent qui n’existe pas.

ENOENT

Tentative d’accĂ©der Ă  (avec access (2)) ou d’ouvrir (avec open (2)) un fichier inexistant du rĂ©pertoire d’un cpuset.

ENOMEM

Pas assez de mémoire disponible pour le noyau ; ceci peut se produire pour différents appels systÚme liés aux cpusets, mais seulement si le systÚme manque beaucoup de mémoire.

ENOSPC

Tentative d’écriture (avec write (2)) de l’identifiant d’un processus dans le fichier tasks d’un cpuset alors que les fichiers cpuset.cpus ou cpuset.mems sont vides.

ENOSPC

Tentative d’écriture (avec write (2)) d’un fichier cpuset.cpus ou cpuset.mems vide dans un cpuset auquel sont attachĂ©es des tĂąches.

ENOTDIR

Tentative de renommage (avec rename (2)) d’un cpuset qui n’existe pas.

EPERM

Tentative de suppression d’un fichier dans le rĂ©pertoire d’un cpuset.

ERANGE

Une liste pour cpuset.cpus ou cpuset.mems a Ă©tĂ© fournie au noyau mais comprend un nombre trop grand pour que le noyau l’ajoute Ă  son champ de bits.

ESRCH

Tentative d’écriture (avec write (2)) de l’identifiant d’un processus inexistant dans le fichier tasks d’un cpuset.

VERSIONS

Cpusets est apparu pour la premiÚre fois dans Linux 2.6.12.

NOTES

Contrairement Ă  ce que son nom indique, le paramĂštre pid est en fait un identifiant de thread. Chaque thread d’un groupe de threads peut ĂȘtre attachĂ© un cpuset diffĂ©rent. La valeur renvoyĂ©e par un appel Ă  gettid (2) peut ĂȘtre fournie comme paramĂštre pid .

BOGUES

Les fichiers cpuset.memory_pressure peuvent ĂȘtre ouverts en Ă©criture en demandant une crĂ©ation ou troncature, mais dans ce cas write (2) Ă©chouera en positionnant errno Ă  EACCES , et les options de crĂ©ation ou de troncature de open (2) n’ont aucun effet.

EXEMPLES

Voici des exemples pour l’affichage et la modification d’options d’un cpuset Ă  l’aide d’un interprĂ©teur de commandes.

CrĂ©er et s’attacher Ă  un cpuset.

Voici les Ă©tapes pour crĂ©er un nouveau cpuset et lui attacher l’interprĂ©teur de commandes en cours :

(1)

mkdir /dev/cpuset (si ce n’est dĂ©jĂ  fait)

(2)

mount -t cpuset none /dev/cpuset (si ce n’est dĂ©jĂ  fait)

(3)

Créer un nouveau cpuset avec mkdir (1).

(4)

Assigner des CPU et nƓuds mĂ©moire au nouveau cpuset.

(5)

Attacher l’interprĂ©teur de commandes au nouveau cpuset.

Par exemple, la sĂ©quence de commandes suivante dĂ©finira un cpuset appelĂ© « Charlie », ne contenant que les CPU 2 et 3 et le nƓud mĂ©moire 1, et attachera l’interprĂ©teur de commandes en cours Ă  ce cpuset.

$ mkdir /dev/cpuset
$ mount -t cpuset cpuset /dev/cpuset
$ cd /dev/cpuset
$ mkdir Charlie
$ cd Charlie
$ /bin/echo 2-3 > cpuset.cpus
$ /bin/echo 1 > cpuset.mems
$ /bin/echo $$ > tasks
# Le shell en cours s’exĂ©cute dĂ©sormais dans le cpuset Charlie
# La ligne suivante devrait afficher « /Charlie »
$ cat /proc/self/cpuset

DĂ©placer des tĂąches sur d’autres nƓuds mĂ©moire.

Pour dĂ©placer les tĂąches attachĂ©es Ă  un cpuset sur d’autres CPU et d’autres nƓuds mĂ©moire du systĂšme et dĂ©placer les pages mĂ©moires actuellement allouĂ©es par ces processus, effectuez les Ă©tapes suivantes :

(1)

Supposons qu’il faille dĂ©placer les tĂąches du cpuset alpha (les CPU 4–7 et nƓuds mĂ©moire 2–3) vers un autre cpuset beta (CPU 16–19 et nƓuds mĂ©moire 8–9).

(2)

CrĂ©er d’abord le nouveau cpuset beta .

(3)

Autoriser les CPU 16–19 et les nƓuds mĂ©moire 8–9 pour beta .

(4)

Activer memory_migration dans beta .

(5)

DĂ©placer chaque tĂąche d’ alpha vers beta .

La séquence de commandes suivante effectue cela.

$ cd /dev/cpuset
$ mkdir beta
$ cd beta
$ /bin/echo 16-19 > cpuset.cpus
$ /bin/echo 8-9 > cpuset.mems
$ /bin/echo 1 > cpuset.memory_migrate
$ while read i; do /bin/echo $i; done < ../alpha/tasks > tasks

La sĂ©quence ci-dessus dĂ©place tous les processus de alpha vers beta et dĂ©place toute mĂ©moire utilisĂ©e par ces processus sur les nƓuds mĂ©moire 2–3 vers les nƓuds mĂ©moire 8–9.

Notez que la derniĂšre Ă©tape de la sĂ©quence ci-dessus n’était pas :

$ cp ../alpha/tasks tasks

La boucle while , plutĂŽt que l’utilisation de la commande cp (1), est nĂ©cessaire par ce qu’un seul identifiant de processus Ă  la fois peut ĂȘtre Ă©crit dans le fichier tasks .

La mĂȘme chose (l’écriture d’un PID Ă  la fois) peut se faire plus efficacement qu’avec la boucle while , en moins de caractĂšre et dans une syntaxe qui fonctionne avec tous les interprĂ©teurs de commandes mais malheureusement de façon moins intelligible, en utilisant l’option -u (sans tampon) de sed (1) :

$ sed -un p < ../alpha/tasks > tasks

VOIR AUSSI

taskset (1), get_mempolicy (2), getcpu (2), mbind (2), sched_getaffinity (2), sched_setaffinity (2), sched_setscheduler (2), set_mempolicy (2), CPU_SET (3), proc (5), cgroups (7), numa (7), sched (7), migratepages (8), numactl (8)

Documentation/admin-guide/cgroup-v1/cpusets.rst dans l’arborescence des sources du noyau Linux (ou Documentation/cgroup-v1/cpusets.txt avant Linux 4.18 et Documentation/cpusets.txt avant Linux 2.6.29)

TRADUCTION

La traduction française de cette page de manuel a été créée par Christophe Blaess <https://www.blaess.fr/christophe/>, Stéphan Rafin <stephan.rafin@laposte.net>, Thierry Vignaud <tvignaud@mandriva.com>, François Micaux, Alain Portal <aportal@univ-montp2.fr>, Jean-Philippe Guérard <fevrier@tigreraye.org>, Jean-Luc Coulon (f5ibh) <jean-luc.coulon@wanadoo.fr>, Julien Cristau <jcristau@debian.org>, Thomas Huriaux <thomas.huriaux@gmail.com>, Nicolas François <nicolas.francois@centraliens.net>, Florentin Duneau <fduneau@gmail.com>, Simon Paillard <simon.paillard@resel.enst-bretagne.fr>, Denis Barbier <barbier@debian.org>, David Prévot <david@tilapin.org>, Cédric Boutillier <cedric.boutillier@gmail.com>, Frédéric Hantrais <fhantrais@gmail.com> et Jean-Pierre Giraud <jean-pierregiraud@neuf.fr>

Cette traduction est une documentation libre ; veuillez vous reporter à la GNU General Public License version 3 concernant les conditions de copie et de distribution. Il n’y a aucune RESPONSABILITÉ LÉGALE.

Si vous découvrez un bogue dans la traduction de cette page de manuel, veuillez envoyer un message à debian-l10n-french@lists.debian.org .