cpuset(7) Miscellaneous Information Manual cpuset(7)
NOM
cpuset - Confiner des processus a des sous-ensembles de processeurs et
de noeuds memoire
DESCRIPTION
Le systeme de fichiers cpuset (N.d.T. : << cpuset >> signifie mot a mot
<< ensemble de CPU >>, mais comme il ne s'agit pas uniquement
d'ensembles de CPU, le terme cpuset sera utilise par la suite) est une
interface sous forme d'un pseudosysteme de fichiers pour le mecanisme
<< cpuset >> du noyau, qui permet de controler le placement de
processus sur des processeurs ou en memoire. Il est habituellement
monte dans /dev/cpuset.
Sur les systemes dont le noyau a ete compile avec la prise en charge
des cpusets, tous les processus sont attaches a un cpuset, et les
cpusets sont toujours presents. Si un systeme prend en charge les
cpusets, alors il aura une entree nodev cpuset dans le fichier
/proc/filesystems. En montant le systeme de fichiers cpuset (consultez
la section EXEMPLE ci-dessous), l'administrateur peut configurer les
cpusets d'un systeme pour controler le placement des processus sur les
CPU et dans la memoire sur de systeme. Par defaut, si la configuration
des cpusets d'un systeme n'est pas modifiee ou si le systeme de
fichiers cpuset n'est meme pas monte, le mecanisme des cpusets, meme
s'il est present, n'a pas d'effets sur le comportement du systeme.
Un cpuset definit une liste de CPU et de noeuds memoire.
Les CPU d'un systeme comprennent toutes les unites de traitement
logiques sur lesquelles peuvent s'executer des processus, comprenant,
s'il y en a, les differents coeurs d'un processeur et les Hyper-Threads
d'un coeur de processeur. Les noeuds memoire comprennent tous les bancs
distinct de memoire ; les petits systemes et les systemes SMP ont
typiquement un seul noeud memoire qui contient toute la memoire du
systeme, alors que les systemes NUMA (<< non-uniform memory access >> :
acces non uniforme a la memoire) ont plusieurs noeuds memoire.
Les cpusets sont representes par des repertoires dans un pseudosysteme
de fichiers hierarchique dont le repertoire de plus haut niveau
(/dev/cpuset) represente le systeme complet (tous les CPU et noeuds
memoire en ligne). Tout cpuset fils (le descendant) d'un autre cpuset
pere contient un sous-ensemble des CPU et des noeuds memoire du pere.
Les repertoires et les fichiers qui representent les cpusets ont les
permissions habituelles des systemes de fichiers.
Chaque processus du systeme appartient a un unique cpuset. Un processus
est oblige de s'executer sur les CPU du cpuset auquel il appartient et
est oblige d'allouer de la memoire uniquement sur les noeuds memoire de
ce cpuset. Quand un processus cree un fils avec fork(2), le processus
fils est place dans le meme cpuset que le processus pere. S'il a les
privileges suffisants, le processus fils peut se deplacer d'un cpuset a
un autre et les CPU ou noeuds memoire d'un cpuset existant peuvent etre
changes.
Au debut du demarrage du systeme, un seul cpuset est defini qui
comprend tous les CPU et tous les noeuds memoire du systeme et tous les
processus se trouvent dans ce cpuset. Pendant le demarrage ou par la
suite lors de l'execution normale du systeme, d'autres cpusets peuvent
etre crees, en tant que sous-repertoire de ce cpuset de plus haut
niveau, sous le controle de l'administrateur systeme. Des processus
peuvent etre places dans ces autres cpusets.
Les cpusets sont integres dans le noyau avec le mecanisme d'affinite
d'ordonnancement de sched_setaffinity(2) et les mecanismes de placement
en memoire de mbind(2) et set_mempolicy(2). Aucun de ces mecanismes ne
permettent a un processus d'utiliser un CPU ou un noeud memoire qui
n'est pas autorise par le cpuset du processus. Si une modification du
cpuset entre en conflit avec ces autres mecanismes, le placement dans
le cpuset est force, meme si cela signifie qu'il faut outrepasser ces
autres mecanismes. Ceci est fait silencieusement par le noyau en
restreignant les CPU et noeuds memoire demandes par ces autres
mecanismes a ceux qui sont autorises par le cpuset du processus
appelant. Ces autres appels peuvent alors renvoyer une erreur si, par
exemple, ils sont amenes a demander un ensemble vide de CPU ou de
noeuds memoire apres que la demande est restreinte au cpuset du
processus appelant.
Typiquement, un cpuset est utilise pour gerer le confinement dans des
CPU ou des noeuds memoire pour un ensemble de processus qui cooperent
entre eux, comme un ordonnanceur de taches, et ces autres mecanismes
permettent de gerer le placement de chacun des processus ou des regions
memoire pour chacune de ces taches.
FICHIERS
Chaque repertoire de /dev/cpuset represente un cpuset et contient un
ensemble definit de pseudofichiers qui decrivent l'etat de ce cpuset.
Les nouveaux cpusets sont crees avec l'appel systeme mkdir(2) ou la
commande mkdir(1). Les proprietes d'un cpuset, comme ses drapeaux, les
CPU et noeuds memoire autorises et les processus attaches sont
recuperes ou modifies en lisant ou ecrivant dans le fichier approprie
du repertoire du cpuset. Ces fichiers sont decrits ci-dessous.
Les pseudofichiers dans chaque repertoire d'un cpuset sont crees
automatiquement quand le cpuset est cree, suite a l'appel a mkdir(2).
Il n'est pas possible d'ajouter ou de supprimer directement ces
pseudofichiers.
Le repertoire d'un cpuset qui ne contient pas de repertoire pour un
cpuset fils et n'a pas de processus lui etant attache peut etre
supprime a l'aide de rmdir(2) ou rmdir(1). Il n'est pas necessaire, ou
possible, de supprimer les pseudofichiers du repertoire avant de le
supprimer.
Les pseudofichiers des repertoires d'un cpuset sont de petits fichiers
textes qui peuvent etre lus ou ecrits en utilisant les outils
traditionnels comme cat(1) et echo(1) ou depuis un programme en
utilisant des fonctions d'une bibliotheque d'entrees sorties ou des
appels systeme, comme open(2), read(2), write(2) et close(2).
Les pseudofichiers dans un repertoire d'un cpuset representent l'etat
interne du noyau et n'ont pas de representation persistante sur le
disque. Les fichiers d'un cpuset sont listes et decrits ci-dessous.
tasks Liste des identifiants de processus (PID) des processus dans ce
cpuset. La liste contient une serie de nombres decimaux au
format ASCII, chacun suivit d'une nouvelle ligne. Un processus
peut etre ajoute a un cpuset (ce qui le supprime automatiquement
du cpuset qui le contenait auparavant) en ecrivant son PID dans
le fichier tasks du cpuset (avec ou sans nouvelle ligne a la
fin).
Attention : un seul PID peut etre ecrit a la fois dans le
fichier tasks. Si une chaine est ecrite et qu'elle contient plus
d'un PID, seul le premier sera utilise.
notify_on_release
Drapeau (0 ou 1). Lorsqu'il est active (1), ce cpuset sera gere
de facon particuliere une fois qu'il sera libere, c'est-a-dire
apres que tous les processus cessent de l'utiliser (c'est-a-dire
se terminent ou ont ete deplaces dans un autre ensemble de CPU)
et que tous les repertoires des cpusets fils ont ete supprimes.
Consultez la section Notification a la liberation ci-dessous.
cpuset.cpus
Liste des numeros physiques des CPU sur lesquels les processus
de ce cpuset ont le droit de s'executer. Consultez la section
Format des listes ci-dessous pour une description du format de
cpus.
Les CPU autorises pour un cpuset peuvent etre changes en
ecrivant une nouvelle liste dans la fichier cpus.
cpuset.cpu_exclusive
Drapeau (0 ou 1). S'il est active (1), le cpuset a un acces
exclusif a ses CPU (des cpusets freres ou cousins ne peuvent pas
partager de CPU). Par defaut, il est desactive (0). Les cpusets
nouvellement crees ont aussi ce drapeau de desactive (0) au
debut.
Deux cpusets sont freres s'ils ont le meme cpuset pere dans la
hierarchie /dev/cpuset. Deux cpusets sont cousins si aucun n'est
l'ancetre de l'autre. Independamment du parametre cpu_exclusive,
si un cpuset est l'ancetre 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 pere.
cpuset.mems
Liste des noeuds memoire sur lesquels les processus de ce cpuset
ont le droit d'allouer de la memoire. 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 active (1), le cpuset a un acces
exclusif a ses noeuds memoire (pas de partage entre freres ou
cousins). S'il est active (1), il s'agit egalement d'un cpuset
<< Hardwall >> (voir ci-dessous). Par defaut, il est desactive
(0). Les cpusets nouvellement crees ont aussi ce drapeau de
desactive (0) au debut.
Independamment du parametre mem_exclusive, si un cpuset est
l'ancetre d'un autre, alors leurs noeuds memoires doivent se
chevaucher parce que l'ensemble des noeuds memoire d'un cpuset
est toujours un sous ensemble des noeuds memoire du cpuset pere.
cpuset.mem_hardwall (depuis Linux 2.6.26)
Drapeau (0 ou 1). S'il est active (1), le cpuset est de type
Hardwall (voir ci-dessous). Contrairement a mem_exclusive, des
cpusets marques avec mem_hardwall peuvent partager des noeuds
memoire avec des cpusets freres ou cousins. Par defaut, il est
desactive (0). Les cpusets nouvellement crees ont aussi ce
drapeau de desactive (0) au debut.
cpuset.memory_migrate (depuis Linux 2.6.16)
Drapeau (0 ou 1). S'il est active (1), alors la migration
memoire est activee. Par defaut, il est desactive (0). Consultez
la section Migration memoire ci-dessous.
cpuset.memory_pressure (depuis Linux 2.6.16)
Une mesure de la pression memoire causee par les processus d'un
cpuset. Consultez la section Pression memoire ci-dessous. A
moins que memory_pressure_enabled soit active, il vaut toujours
zero. 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 present que dans le cpuset
racine, qui est normalement /dev/cpuset. S'il est active (1),
les calculs de memory_pressure sont actives pour tous les
cpusets du systeme. Par defaut, il est desactive (0). Consultez
la section Pression memoire ci-dessous.
cpuset.memory_spread_page (depuis Linux 2.6.17)
Drapeau (0 ou 1). S'il est active (1), les pages du cache de
pages du noyau (les tampons des systemes de fichiers) sont
distribuees uniformement dans les cpusets. Par defaut, il est
desactive (0) dans le cpuset racine et herite du cpuset parent
pour les cpusets nouvellement crees. Consultez la section
Repartition memoire ci-dessous.
cpuset.memory_spread_slab (depuis Linux 2.6.17)
Drapeau (0 ou 1). S'il est active (1), les caches slab (N.d.T. :
tampons prealloues par le noyau) pour les entrees-sorties de
fichiers (des structures pour des repertoires ou inoeuds) sont
repartis uniformement dans le cpuset. Par defaut, ce drapeau est
desactive (0) dans le cpuset racine et les nouveaux cpusets
heritent du drapeau de leur parent quand ils sont crees.
Consultez la section Repartition memoire ci-dessous.
cpuset.sched_load_balance (depuis Linux 2.6.24)
Drapeau (0 ou 1). S'il est active (1, la valeur par defaut), le
noyau repartira automatiquement la charge des processus du
cpuset au travers les CPU autorises pour le cpuset. S'il est
desactive (0), le noyau ne repartira pas la charge des processus
du cpuset, a moins qu'un autre cpuset qui partage des CPU avec
lui n'ait son drapeau sched_load_balance active. Consultez la
section Repartition de la charge par l'ordonnanceur ci-dessous
pour plus de details.
cpuset.sched_relax_domain_level (depuis Linux 2.6.26)
Entier, compris entre -1 et une petite valeur positive.
sched_relax_domain_level controle la largeur de l'intervalle des
CPU pour lesquels le noyau effectue une repartition immediate
des taches executables. Si sched_load_balance est desactive,
alors sched_relax_domain_level ne compte pas, puisqu'il n'y a
pas de repartition de la charge. Si sched_load_balance est
active, alors plus sched_relax_domain_level est important, plus
l'intervalle des CPU sur lesquels le noyau essaie de repartir la
charge est important. Consultez la section Niveau du domaine de
detente de l'ordonnanceur ci-dessous pour plus de details.
En plus des pseudofichiers decrits ci-dessus, dans chaque repertoire de
/dev/cpuset, chaque processus a un pseudofichier, /proc/pid/cpuset, qui
indique le chemin vers le repertoire du cpuset du processus,
relativement a la racine du systeme de fichiers cpuset.
Quatre lignes sont egalement ajoutees dans le fichier /proc/pid/status,
fournissant pour chaque processus les champs : Cpus_allowed (sur quels
CPU il peut etre ordonnance) et Mems_allowed (sur quels noeuds memoire
de la memoire peut etre allouee), 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 ete ajoutes dans Linux 2.6.24 ; les champs
<< allowed_list >> ont ete ajoutes dans Linux 2.6.26.
CAPACITES ETENDUES
En plus de controler quels CPU (cpus) et noeuds memoire (mems) un
processus a le droit d'utiliser, les cpusets fournissent les
fonctionnalites etendues suivantes.
Ensembles de CPU exclusifs
Si un cpuset est marque avec cpu_exclusive ou mem_exclusive, aucun
autre cpuset, autre que des ancetres ou descendants directs, peuvent
partager des CPU ou des noeuds memoire avec ce cpuset.
Un cpuset dont mem_exclusive est active restreint les allocations du
noyau pour les pages des tampons de cache et autres donnees internes du
noyau communement partagees par le noyau au travers differents
utilisateurs. Tous les cpusets, que mem_exclusive soit active ou non,
restreignent l'allocation de memoire depuis l'espace utilisateur. Ceci
permet de configurer un systeme de telle sorte que differentes taches
puissent partager des donnees du noyau, tout en isolant toutes les
allocations en mode utilisateur des taches dans leur propre cpuset.
Pour ceci, il faut creer un gros cpuset, avec mem_exclusive active,
pour contenir toutes les taches, et creer des cpuset fils sans
mem_exclusive pour chacune des taches. Seule une petite partie de la
memoire du noyau, comme les requetes des gestionnaires d'interruptions,
est autorisee a etre placee sur des noeuds memoire en dehors d'un
cpuset, meme si mem_exclusive est active.
Hardwall
Un cpuset pour lequel mem_exclusive ou mem_hardwall est active est un
cpuset hardwall. Un cpuset hardwall restreint les allocations memoire
du noyau pour les pages, tampons et toutes autre donnees partages
frequemment par le noyau au travers differents utilisateurs. Tous les
cpusets, hardwall ou non, restreignent les allocations memoire pour
l'espace utilisateur.
Ceci permet de configurer un systeme de telle sorte que differentes
taches independantes puissent partager des donnees du noyau, comme des
pages des systemes de fichiers, tout en isolant les allocations de
l'espace utilisateur de chaque tache dans leur cpuset. Pour ceci, il
faut creer un gros cpuset hardwall qui contiendra toutes les taches et
creer des cpusets fils (non hardwall) pour chacune des taches.
Seule une petite quantite de memoire noyau, comme les demandes des
gestionnaires d'interruption, peut etre utilisee a l'exterieur d'un
cpuset hardwall.
Notification a la liberation
Si le drapeau notify_on_release d'un cpuset est active (1), alors quand
le dernier processus quitte le cpuset (il se termine ou s'attache a un
autre cpuset) et que le dernier cpuset fils de ce cpuset a ete
supprime, le noyau executera la commande /sbin/cpuset_release_agent en
lui fournissant le chemin (relatif au point de montage du systeme de
fichiers cpuset) du cpuset abandonne. Ceci permet de supprimer
automatiquement les cpusets abandonnes.
Le drapeau notify_on_release du cpuset racine est desactive (0) par
defaut au moment du demarrage. La valeur par defaut pour les autres
cpusets lors de leur creation est egale a la valeur de
notify_on_release de leur cpuset parent.
La commande /sbin/cpuset_release_agent est appelee, avec dans argv[1]
le nom (un chemin relatif a /dev/cpuset) du cpuset a 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 etre modifie
en ecrivant un 0 ou un 1 ASCII (avec ou sans fin de ligne) dans le
fichier pour respectivement desactiver ou activer le drapeau.
Pression memoire
Le fichier memory_pressure d'un cpuset indique la moyenne instantanee
du taux auquel les processus du cpuset tentent de liberer de la memoire
utilisee sur les noeuds du cpuset pour satisfaire les nouvelles
demandes de memoire.
Ceci permet a un gestionnaire de taches de superviser les taches qui
s'executent dans des cpuset dedies et detecter efficacement la pression
memoire qu'une tache produit.
Ceci est utile a la fois pour les systemes tres surveilles qui
executent diverses taches qui leurs sont fournies et peuvent choisir de
terminer ou de changer la priorite des taches qui essaient d'utiliser
plus de memoire que les noeuds memoire qui leurs ont ete assignes leurs
permettent, et les systemes pour du calcul scientifique avec des taches
paralleles, fortement couplees, au temps d'execution important, qui ne
pourraient plus fournir les performances demandees si elles se
mettaient a utiliser plus de memoire qu'elles n'en ont droit.
Ce mecanisme fourni un moyen tres economique pour detecter des signes
de pression memoire sur un cpuset. L'action a effectuer lorsqu'un signe
de pression memoire est detecte est laisse au libre arbitre du
gestionnaire des taches ou autre code utilisateur.
A moins que le calcul de la pression memoire soit active par le
pseudofichier /dev/cpuset/cpuset.memory_pressure_enabled, cette
pression memoire n'est calculee pour aucun cpuset et les lectures dans
les fichiers memory_pressure renvoient toujours zero, c'est-a-dire la
chaine ASCII << 0\en >>. Consultez la section AVERTISSEMENTS
ci-dessous.
Une moyenne instantanee par cpuset est utilisee pour les raisons
suivantes :
- Comme cette metrique est par cpuset plutot que par processus ou par
region memoire virtuelle, la charge du systeme due a la supervision
de cette metrique par un ordonnanceur de taches est fortement
reduite sur les gros systemes, etant donne qu'il n'est pas
necessaire de parcourir la liste des taches a chaque fois.
- Comme cette metrique est une moyenne instantanee plutot qu'un
compteur, un ordonnanceur de taches obtient la pression memoire en
une seule lecture sans avoir a lire et se souvenir des resultats
pendant un certain temps.
- Comme cette metrique est par cpuset plutot que par processus,
l'ordonnanceur de taches peut obtenir l'information importante, la
pression memoire dans un cpuset, en une seule lecture sans
necessiter d'obtenir et de se souvenir des resultats pour tous les
processus d'un cpuset (la liste des processus peut changer
dynamiquement).
La pression memoire d'un cpuset est calculee en utilisant un simple
filtre digital par cpuset dans le noyau. Pour chaque cpuset, ce filtre
suit le taux auquel les processus attaches a ce cpuset demandent au
noyau de reutiliser de la memoire.
Ces demandes de reutilisation de memoire se produisent quand un
processus doit satisfaire une demande de page memoire en trouvant
d'abord une page a reutiliser, du fait de l'absence de page disponible
deja prete. Les pages sales des systemes de fichiers sont reutilisees
en les ecrivant d'abord sur le disque. Les tampons des systemes de
fichiers qui n'ont pas ete modifies sont reutilises tout simplement en
les abandonnant, mais si cette page est necessaire de nouveau, il
faudra la relire sur le disque.
Le fichier cpuset.memory_pressure fournit un nombre entier qui
represente le taux des demandes recentes (la demi-vie est de
10 secondes) de reutilisation de memoire par les processus du cpuset,
l'unite etant le nombre de demandes par seconde fois 1000.
Repartition memoire
Il y a deux fichiers, par cpuset, pour des drapeaux booleens qui
controlent ou le noyau alloue les pages pour les tampons des systemes
de fichiers et les structures de donnees liees internes au noyau. Ces
fichiers sont cpuset.memory_spread_page et cpuset.memory_spread_slab.
Si le drapeau booleen cpuset.memory_spread_page est active, alors le
noyau repartit les tampons des systemes de fichiers (les caches des
pages) equitablement sur tous les noeuds autorises pour le processus
qui demande la page, au lieu de placer ces pages de preference sur le
noeud sur lequel s'execute le processus.
Si le drapeau booleen cpuset.memory_spread_slab d'un cpuset est active,
alors le noyau repartira uniformement les caches slab lies aux systemes
de fichiers, comme ceux pour des entrees d'inoeuds ou de repertoires,
sur tous les noeuds autorises pour le processus qui demande de la
memoire, plutot que de preferer mettre ces pages sur le noeud sur
lequel s'execute le processus.
La configuration de ces drapeaux n'affecte pas les pages du segment de
donnees (consultez brk(2)) ou du segment de la pile d'un processus.
Par defaut, les deux types de repartition de la memoire sont desactives
et le noyau prefere allouer la memoire sur le noeud local ou s'execute
le processus. Si ce noeud n'est pas autorise par la politique NUMA du
processus ou par la configuration des cpusets ou s'il n'y a plus
suffisamment de pages memoire disponibles sur ce noeud, alors le noyau
recherche le noeud le plus proche etant autorise et ayant suffisamment
de pages disponibles.
Quand un nouveau cpuset est cree, il herite de la configuration de
repartition memoire de son pere.
Activer la repartition memoire a pour effet d'ignorer la politique
memoire NUMA du processus pour les allocations de pages ou de caches
slab, qui sont alors eparpillees. Cependant, les changements dus a la
repartition memoire demandee par un cpuset ne sont pas visibles pour
les appels systeme mbind(2) ou set_mempolicy(2). Ces deux appels
systeme lies a la politique memoire NUMA semblent se comporter comme si
aucune repartition memoire n'etait demandee par un cpuset, meme si
c'est le cas. Si la repartition memoire est par la suite desactivee
pour les cpuset, la derniere politique memoire NUMA definie par ces
appels est automatiquement appliquee de nouveau.
cpuset.memory_spread_page et cpuset.memory_spread_slab sont tous les
deux des fichiers contenant des drapeaux booleens. Par defaut, ils
contiennent un << 0 >>, ce qui signifie que la fonctionnalite est
desactivee pour ce cpuset. Si un << 1 >> est ecrit dans le fichier, la
fonctionnalite correspondante est activee.
La repartition memoire d'un cpuset se comporte de facon similaire a ce
qui est connu (dans d'autres contextes) comme le placement memoire a
tour de role (<< round-robin >>) ou entrelace (<< interleave >>).
La configuration d'une strategie de repartition memoire pour un cpuset
peut ameliorer significativement les performances pour les taches qui :
- necessitent de placer les donnees locales des threads dans des
noeuds memoire proches des CPU qui executent les threads qui
accedent le plus frequemment a ces donnees ; mais aussi
- necessitent d'acceder a de gros ensembles de donnees de systemes de
fichiers qui doivent etre repartis sur differents noeuds du cpuset
de la tache du fait de leurs tailles.
Sans cette politique, la repartition des allocations memoire sur les
noeuds du cpuset de la tache peut ne pas etre equitable,
particulierement pour les taches qui n'auraient qu'un thread charge de
l'initialisation ou de la lecture des donnees d'entree.
Migration memoire
Normalement, avec la configuration de cpuset.memory_migrate par defaut
(desactive), une fois qu'une page est allouee (une page physique de la
memoire lui est donnee), cette page reste sur le noeud ou elle a ete
allouee, tant qu'elle reste allouee, meme si la politique de placement
memoire du cpuset (mems) change par la suite.
Quand la migration memoire est activee pour un cpuset, si la
configuration de mems est modifiee alors toute page memoire utilisee
par un processus du cpuset qui se trouverait sur un noeud memoire qui
n'est plus autorise sera deplacee sur un noeud memoire qui est
autorise.
De plus, si un processus est deplace dans un cpuset dont le drapeau
memory_migrate est active, toutes les pages memoire qu'il utilise et
qui se trouvent sur des noeuds memoire qui etaient autorises dans son
cpuset precedant mais ne le sont plus dans le nouveau cpuset seront
deplacees sur un noeud memoire autorise pour le nouveau cpuset.
L'emplacement relatif d'un page deplacee d'un cpuset est preserve si
possible lors de ces operations de deplacement. Par exemple, si la page
se trouvait sur le deuxieme noeud valable du precedent cpuset, alors la
page sera placee sur le deuxieme noeud valable du nouveau cpuset, si
c'est possible.
Repartition de la charge par l'ordonnanceur
L'ordonnanceur du noyau repartit automatiquement la charge des
processus. Si un CPU est sous-utilise, le noyau recherchera des
processus sur d'autres CPU plus charges et deplacera ces processus sur
le CPU sous-utilise a condition que les mecanismes comme les cpuset et
sched_setaffinity(2) le permettent.
Le cout de l'algorithme de repartition de la charge et son impact sur
les structures de donnees partagees du noyau, comme la liste des
processus, augmente plus que lineairement avec le nombre de CPU qui
interviennent pour la repartition de la charge. Par exemple le cout
pour la repartition de la charge dans un grand ensemble de CPU sera
superieur a celui pour la repartition de la charge dans deux ensembles
ayant moitie moins de CPU. (La relation entre le nombre de CPU
intervenant dans la repartition de la charge et le cout de cette
repartition de charge depend de l'implementation de l'ordonnanceur de
processus du noyau, qui change dans le temps quand de meilleurs
algorithmes d'ordonnancement sont implementes)
Le drapeau sched_load_balance d'un cpuset permet de supprimer cette
repartition automatique de la charge dans les cas ou elle n'est pas
necessaire et que sa suppression ameliorerait les performances.
Par defaut, la repartition de la charge se fait sur tous les CPU, a
l'exception de ceux marques comme etant isoles en utilisant au moment
du demarrage le parametre du noyau << isolcpus= >>. (Consultez la
section Niveau du domaine de detente de l'ordonnanceur ci-dessous pour
changer le comportement par defaut)
Cette repartition de la charge par defaut n'est pas bien adaptee aux
situations suivantes :
- Sur les gros systemes, la repartition de la charge sur beaucoup de
CPU est tres couteuse. Si le systeme est gere avec des cpusets pour
placer les taches independantes sur differents ensembles de CPU, une
repartition de la charge complete n'est pas necessaire.
- Les systemes avec une prise en charge temps-reel sur certains CPU
doivent minimiser la surcharge du systeme sur ces CPU et donc eviter
la repartition de la charge des processus si elle n'est pas
necessaire.
Quand le drapeau sched_load_balance d'un cpuset est active (ce qui est
le cas par defaut), une repartition de la charge sur tous les CPU
autorises par le cpuset est demande, a condition que le processus
puisse etre deplace d'un CPU du cpuset a un autre CPU (c'est-a-dire
qu'il n'ait pas ete attache a des CPU avec, par exemple,
sched_setaffinity(2)).
Quand le drapeau sched_load_balance d'un cpuset est desactive, alors
l'ordonnanceur evitera de deplacer des processus pour repartir la
charge des CPU du cpuset, sauf si un autre cpuset partage le meme CPU
et a son drapeau sched_load_balance active.
Ainsi, par exemple, si le cpuset racine a son drapeau
sched_load_balance active, alors l'ordonnanceur repartira la charge sur
tous les CPU et la configuration du drapeau sched_load_balance des
autres cpusets n'a pas d'effet, puisqu'une repartition complete de la
charge est deja demandee.
Dans les deux situations ci-dessus, le drapeau sched_load_balance
devrait donc etre desactive sur le cpuset racine et seuls les cpusets
fils plus petits devraient l'activer.
Lorsque vous faites ceci, vous ne devez generalement pas laisser un
processus non attache a un CPU dans le cpuset racine qui pourrait
utiliser les CPU de facon non negligeable. De cette facon les processus
peuvent etre artificiellement contraints a un sous ensemble des CPU en
fonction de la configuration de ce drapeau dans les cpusets
descendants. Meme si ce processus pourrait utiliser des cycles CPU
inutilises par certains CPU, l'ordonnanceur du noyau ne cherchera pas a
repartir la charge du processus sur le CPU sous utilise.
Bien sur, les processus attaches a un CPU particulier peuvent etre
laisses dans un cpuset qui desactive sched_load_balance puisque ces
processus ne peuvent etre deplaces de toute facon.
Niveau du domaine de detente de l'ordonnanceur
L'ordonnanceur du noyau effectue une repartition de la charge immediate
lorsqu'un CPU devient disponible ou lorsqu'une autre tache est prete.
Cette repartition de la charge permet de s'assurer que le plus de CPU
possibles sont utilises efficacement en executant des taches. Le noyau
effectue aussi une repartition de la charge de facon plus sporadique
sur la base de l'horloge logicielle decrite dans time(7). La
configuration de sched_relax_domain_level ne s'applique qu'a la
repartition de charge automatique. Independamment de la configuration
de sched_relax_domain_level, une repartition de charge sporadique est
effectuee a travers tous les CPU (sauf si cela a ete desactive avec
sched_load_balance). Dans tous les cas, bien sur, les taches ne seront
executees que sur les CPU autorises par leur cpuset et par les appels
systemes sched_setaffinity(2).
Sur les petits systemes, avec peu de CPU, la repartition de charge
immediate est utile pour ameliorer l'interactivite du systeme et
minimiser les cycles CPU inutilises. Mais sur les gros systemes,
essayer de repartir la charge immediatement sur un nombre important de
CPU peut etre plus couteux que ce que ca ne rapporte, en fonction des
performances des differentes taches et du materiel.
La signification exacte des petites valeurs de sched_relax_domain_level
dependra de l'implementation de l'ordonnanceur du noyau et de
l'architecture non uniforme du materiel. Ces deux parametres evolueront
dans le temps et dependent de l'architecture du systeme et de la
version du noyau.
A ce jour, quand cette capacite a ete 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 immediatement une repartition de la charge sur les
differents Hyper-Thread freres d'un meme coeur.
2 Effectuer immediatement une repartition de la charge sur les
differents coeurs d'un processeur.
3 Effectuer immediatement une repartition de la charge sur les
differents CPU d'un meme noeud ou d'une meme lame.
4 Effectuer immediatement une repartition de la charge sur les
differents (detail d'implementation) noeuds [pour les systemes
NUMA].
5 Effectuer immediatement une repartition de la charge sur tous
les CPU d'un systeme [pour les systemes NUMA].
La valeur zero (0) pour sched_relax_domain_level signifie toujours
qu'il n'y a pas de repartition de charge immediate, et donc la
repartition de la charge s'effectue periodiquement et non pas
immediatement quand un CPU devient disponible ou qu'une tache peut etre
executee.
La valeur -1 pour sched_relax_domain_level signifie toujours qu'il faut
utiliser la valeur par defaut du systeme. La valeur par defaut du
systeme peut varier en fonction de l'architecture et du noyau. Cette
valeur par defaut du systeme peut etre modifiee en fournissant au noyau
un parametre << relax_domain_level= >> lors du demarrage.
Si des cpusets partagent des CPU et ont des valeurs de
sched_relax_domain_level incompatibles, alors la valeur la plus elevee
s'applique a tous les CPU de ces cpusets. Dans ce cas, -1 est la valeur
la plus faible, remplacee par toute autre valeur et -0 est la valeur la
plus faible suivante.
FORMATS
Les formats suivants sont utilises pour representer des ensembles de
CPU et de noeuds memoire.
Affichage sous forme de masque
L'Affichage sous forme de masque est utilise pour representer les
masques de bits des CPU et noeuds memoire dans le fichier
/proc/pid/status.
Ce format affiche chaque mot de 32 bits au format hexadecimal (en
utilisant les caracteres ASCII << 0 >> - << 9 >> et << a >> -
<< f >>) ; le debut des mots est complete par des zeros si necessaire.
Pour les masques de plus d'un mot, une virgule est utilisee pour
separer les mots. Les mots sont affiche au format grand boutiste, avec
le bit le plus significatif en premier. Les chiffres hexadecimaux d'un
mot utilise aussi l'ordre grand boutiste.
Le nombre de mots de 32 bits affiches est le nombre minimal necessaire
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 actives sera
affiche de cette facon :
00000001,00000001,00010117
Le premier << 1 >> correspond au bit 64, le second au bit 32, le
troisieme au bit 16, le quatrieme au bit 8, le cinquieme 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 numeros ou intervalles de CPU ou de noeuds memoire separes par
des virgules, en decimal au format ASCII.
Exemple d'Affichage sous forme de liste :
0-4,9 # bits 0, 1, 2, 3, 4 et 9 actives
0-2,7,12-14 # bits 0, 1, 2, 7, 12, 13 et 14 actives
REGLES
Les regles suivantes s'appliquent a chaque cpuset :
- Ses CPU et noeuds memoire doivent etre des sous-ensembles de ceux de
leur parent (ou les memes ensembles).
- Il ne peut etre marque avec cpu_exclusive que si son parent l'est.
- Il ne peut etre marque avec mem_exclusive que si son parent l'est.
- S'il est marque avec cpu_exclusive, ses CPU ne doivent pas etre
partages avec ses freres.
- S'il est marque avec mem_exclusive, ses noeuds memoire ne doivent
pas etre partages avec ses freres.
PERMISSIONS
Les permissions d'un cpuset sont determinees par les permissions des
repertoires et pseudofichiers du systeme de fichiers cpuset,
normalement monte dans /dev/cpuset.
Par exemple, un processus peut se placer dans un autre cpuset s'il peut
ecrire dans le fichier tasks de ce cpuset. Ceci necessite les
permission d'execution des repertoires a traverser et la permission
d'ecrire dans le fichier tasks.
Une contrainte supplementaire s'applique aux demandes de deplacement
d'autres processus dans un cpuset. Un processus ne peut pas attacher un
autre processus a un cpuset a moins qu'il ait la permission d'envoyer
un signal a ce processus (consultez kill(2)).
Un processus peut creer un cpuset fils s'il a acces et peut ecrire dans
le repertoire du cpuset pere. Il peut modifier les CPU et noeuds
memoire d'un cpuset s'il a acces au repertoire de ce cpuset (les
permissions d'executer tous les repertoires parents) et s'il peut
ecrire dans les fichiers correspondants cpus ou mems.
Il y a une petite difference entre la maniere dont ces permissions sont
evaluees et la maniere dont sont evaluees les permissions pour les
operations sur des systemes de fichiers normaux. Le noyau interprete
les chemins relatifs en fonction du repertoire de travail actuel d'un
processus. Meme quand on opere sur un fichier d'un cpuset, les chemins
relatifs sont interpretes en fonction du repertoire de travail du
processus, et non pas relativement au cpuset actuel du processus. Les
seules facons pour que les chemins de cpusets soient interpretes
relativement au cpuset actuel du processus sont soit que le processus
utilise le repertoire du cpuset comme repertoire de travail (il a
d'abord effectue un cd ou chdir(2) dans le repertoire de son cpuset
dans /dev/cpuset, ce qui est plutot inhabituel), soit que du code
utilisateur convertit le chemin relatif au cpuset en un chemin absolu.
En theorie, ceci signifie que le code utilisateur devrait indiquer les
cpusets en utilisant des chemins absolus, ce qui necessite de connaitre
le point de montage du systeme de fichier cpuset (d'habitude, mais sans
que ce soit necessaire, /dev/cpuset). En pratique, a la connaissance de
l'auteur, tous les utilitaires en mode utilisateur supposent que si le
systeme de fichier cpuset est monte, alors il est monte dans
/dev/cpuset. De plus, une pratique assez courante utilise pour du code
ecrit soigneusement consiste a verifier la presence du pseudofichier
/dev/cpuset/tasks afin de verifier que le pseudosysteme de fichiers
cpuset est bien monte.
AVERTISSEMENTS
Activation de memory_pressure
Par defaut, le fichier cpuset.memory_pressure d'un cpuset vaut zero
(0). A moins que cette fonctionnalite soit activee en ecrivant << 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 utilisee dans un interpreteur de commandes
pour changer les valeurs des fichiers d'un cpuset, soyez conscient que
la commande echo interne a certains interpreteurs de commandes
n'affiche pas de message d'erreur si l'appel systeme write(2) echoue.
Par exemple, si la commande :
echo 19 > cpuset.mems
echoue parce que le noeud memoire numero 19 n'est pas autorise (par
exemple le systeme n'a pas de noeud memoire numero 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'ecriture : argument invalide
EXCEPTIONS
Placement memoire
Les contraintes des cpusets ne s'appliquent pas a toutes les
allocations de memoire systeme pour les raisons suivantes :
Si la fonctionnalite de connexion a chaud est utilisee pour supprimer
tous les CPU d'un cpuset, alors le noyau mettra a jour automatiquement
la liste de CPU autorises (cpus_allowed) de tous les processus attaches
aux CPU du cpuset et autorisera tous les CPU. Le comportement est
similaire lorsque la fonctionnalite de connexion a chaud est utilisee
pour la memoire. En general, le noyau prefere ne pas tenir compte du
placement sur les CPU ou les noeuds memoire plutot que d'abandonner un
processus dont tous les CPU ou noeuds memoire autorises sont
deconnectes. Le code utilisateur devrait reconfigurer les cpusets pour
ne mentionner que les CPU et les noeuds memoire en ligne lorsque la
fonctionnalite de connexion a chaud est utilisee pour ajouter ou
retirer ces ressources.
Quelques demandes d'allocation memoire critiques et internes au noyau,
marquees GFP_ATOMIC, doivent etre satisfaites immediatement. Le noyau
peut rater des demandes ou ne pas fonctionner correctement si certaines
de ces allocations echouent. Si une de ces demandes ne peut etre
satisfaite par le cpuset du processus en cours, alors les contraintes
du cpuset sont relachees et le noyau recherche de la memoire la ou il
peut en trouver. Il est preferable de ne pas respecter un cpuset plutot
que de stresser le noyau.
Les allocations de memoire demandees 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 systeme rename(2) pour renommer des
cpusets. Seuls des renommages simples sont pris en charge ;
c'est-a-dire que changer le nom du repertoire d'un cpuset est autorise,
mais deplacer le repertoire d'un cpuset dans un autre repertoire n'est
pas autorise.
ERREURS
L'implementation des cpusets du noyau Linux positionne errno pour
indiquer la raison de l'echec d'un appel systeme lie a un cpuset.
Les valeurs possible pour errno et leurs significations, lors d'un
echec d'un appel systeme lie a un cpuset sont listees ci-dessous :
E2BIG Tentative d'ecriture (write(2)) dans un fichier special d'un
cpuset avec une longueur superieure a la longueur autorisee par
le noyau pour ces ecritures.
EACCES Tentative d'ecriture (write(2)) d'un identifiant de processus
(PID) dans le fichier tasks d'un cpuset alors que l'appelant
n'est pas autorise a deplacer le processus.
EACCES Tentative d'ajout, avec write(2), d'un CPU ou d'un noeud memoire
dans un cpuset alors que ce CPU ou ce noeud memoire 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 proprietes.
EACCES Tentative d'ecriture (write(2)) dans un fichier
cpuset.memory_pressure.
EACCES Tentative de creation d'un fichier dans le repertoire d'un
cpuset.
EBUSY Tentative de suppression, avec rmdir(2), d'un cpuset auquel sont
attaches 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 noeud memoire d'un
cpuset alors que le CPU ou le noeud memoire se trouve egalement
dans un des fils du cpuset.
EEXIST Tentative de creation, avec mkdir(2), d'un cpuset qui existe
deja.
EEXIST Tentative de renommage (rename(2)) d'un cpuset avec un nom deja
utilise.
EFAULT Tentative de lecture (read(2)) ou d'ecriture (write(2)) dans un
fichier d'un cpuset en utilisant un tampon en dehors de l'espace
memoire 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 respectes pour ce cpuset ou ses freres.
EINVAL Tentative d'ecriture (avec write(2)) d'une liste vide dans
cpuset.cpus ou cpuset.mems pour un cpuset auquel sont deja
attaches des processus ou des cpuset fils.
EINVAL Tentative d'ecriture (avec write(2)) dans cpuset.cpus ou
cpuset.mems d'une liste qui comprend un intervalle dont la borne
superieure est inferieure a la borne inferieure.
EINVAL Tentative d'ecriture (avec write(2)) dans cpuset.cpus ou
cpuset.mems d'une liste dont la chaine comprend un caractere non
valable.
EINVAL Tentative d'ecriture (avec write(2)) dans le fichier cpuset.cpus
d'une liste qui ne comprend aucun CPU en ligne.
EINVAL Tentative d'ecriture (avec write(2)) dans le fichier cpuset.mems
d'une liste qui ne comprend aucun noeud memoire en ligne.
EINVAL Tentative d'ecriture (avec write(2)) dans le fichier cpuset.mems
d'une liste qui comprend un noeud qui ne contient pas de
memoire.
EIO Tentative d'ecriture (avec write(2)) dans le fichier tasks d'un
cpuset d'une chaine qui ne commence pas par un entier decimal au
format ASCII.
EIO Tentative de renommage (avec rename(2)) d'un cpuset dans un
autre repertoire.
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 creation, avec mkdir(2), d'un cpuset dont le nom du
repertoire de base fait plus de 255 caracteres.
ENAMETOOLONG
Tentative de creation, avec mkdir(2), d'un cpuset dont le chemin
complet, prefixe du point de montage compris (typiquement
<< /dev/cpuset/ >>), fait plus de 4095 caracteres.
ENODEV Le cpuset a ete supprime par un autre processus en meme temps
qu'une tentative d'ecriture (avec write(2)) sur un des
pseudofichiers du repertoire du cpuset.
ENOENT Tentative de creation, avec mkdir(2), d'un cpuset dans un cpuset
parent qui n'existe pas.
ENOENT Tentative d'acceder a (avec access(2)) ou d'ouvrir (avec
open(2)) un fichier inexistant du repertoire d'un cpuset.
ENOMEM Pas assez de memoire disponible pour le noyau ; ceci peut se
produire pour differents appels systeme lies aux cpusets, mais
seulement si le systeme manque beaucoup de memoire.
ENOSPC Tentative d'ecriture (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'ecriture (avec write(2)) d'un fichier cpuset.cpus ou
cpuset.mems vide dans un cpuset auquel sont attachees des
taches.
ENOTDIR
Tentative de renommage (avec rename(2)) d'un cpuset qui n'existe
pas.
EPERM Tentative de suppression d'un fichier dans le repertoire d'un
cpuset.
ERANGE Une liste pour cpuset.cpus ou cpuset.mems a ete fournie au noyau
mais comprend un nombre trop grand pour que le noyau l'ajoute a
son champ de bits.
ESRCH Tentative d'ecriture (avec write(2)) de l'identifiant d'un
processus inexistant dans le fichier tasks d'un cpuset.
VERSIONS
Cpusets est apparu pour la premiere fois dans Linux 2.6.12.
NOTES
Contrairement a ce que son nom indique, le parametre pid est en fait un
identifiant de thread. Chaque thread d'un groupe de threads peut etre
attache un cpuset different. La valeur renvoyee par un appel a
gettid(2) peut etre fournie comme parametre pid.
BOGUES
Les fichiers cpuset.memory_pressure peuvent etre ouverts en ecriture en
demandant une creation ou troncature, mais dans ce cas write(2)
echouera en positionnant errno a EACCES, et les options de creation 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 a l'aide d'un interpreteur de commandes.
Creer et s'attacher a un cpuset.
Voici les etapes pour creer un nouveau cpuset et lui attacher
l'interpreteur de commandes en cours :
(1) mkdir /dev/cpuset (si ce n'est deja fait)
(2) mount -t cpuset none /dev/cpuset (si ce n'est deja fait)
(3) Creer un nouveau cpuset avec mkdir(1).
(4) Assigner des CPU et noeuds memoire au nouveau cpuset.
(5) Attacher l'interpreteur de commandes au nouveau cpuset.
Par exemple, la sequence de commandes suivante definira un cpuset
appele << Charlie >>, ne contenant que les CPU 2 et 3 et le noeud
memoire 1, et attachera l'interpreteur de commandes en cours a 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'execute desormais dans le cpuset Charlie
# La ligne suivante devrait afficher << /Charlie >>
$ cat /proc/self/cpuset
Deplacer des taches sur d'autres noeuds memoire.
Pour deplacer les taches attachees a un cpuset sur d'autres CPU et
d'autres noeuds memoire du systeme et deplacer les pages memoires
actuellement allouees par ces processus, effectuez les etapes
suivantes :
(1) Supposons qu'il faille deplacer les taches du cpuset alpha (les
CPU 4-7 et noeuds memoire 2-3) vers un autre cpuset beta (CPU
16-19 et noeuds memoire 8-9).
(2) Creer d'abord le nouveau cpuset beta.
(3) Autoriser les CPU 16-19 et les noeuds memoire 8-9 pour beta.
(4) Activer memory_migration dans beta.
(5) Deplacer chaque tache d'alpha vers beta.
La sequence 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 sequence ci-dessus deplace tous les processus de alpha vers beta et
deplace toute memoire utilisee par ces processus sur les noeuds memoire
2-3 vers les noeuds memoire 8-9.
Notez que la derniere etape de la sequence ci-dessus n'etait pas :
$ cp ../alpha/tasks tasks
La boucle while, plutot que l'utilisation de la commande cp(1), est
necessaire par ce qu'un seul identifiant de processus a la fois peut
etre ecrit dans le fichier tasks.
La meme chose (l'ecriture d'un PID a la fois) peut se faire plus
efficacement qu'avec la boucle while, en moins de caractere et dans une
syntaxe qui fonctionne avec tous les interpreteurs de commandes mais
malheureusement de facon 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 francaise de cette page de manuel a ete creee par
Christophe Blaess , Stephan Rafin
, Thierry Vignaud ,
Francois Micaux, Alain Portal , Jean-Philippe
Guerard , Jean-Luc Coulon (f5ibh) , Julien Cristau , Thomas
Huriaux , Nicolas Francois
, Florentin Duneau
, Simon Paillard , Denis Barbier , David Prevot
, Cedric Boutillier ,
Frederic Hantrais et Jean-Pierre Giraud
Cette traduction est une documentation libre ; veuillez vous reporter a
la GNU General Public License version 3
concernant les conditions
de copie et de distribution. Il n'y a aucune RESPONSABILITE LEGALE.
Si vous decouvrez un bogue dans la traduction de cette page de manuel,
veuillez envoyer un message a .
Pages du manuel de Linux 6.12 15 juin 2024 cpuset(7)