Historique: CGroup
Aperçu de cette version: 54
Cette page de documentation explique comment obtenir le droit d'utiliser des applications en mode temps réel grâce aux cgroups sur un système GNU/Linux. Elle s'applique à quelques distributions actuelles, comme la version standard d'ubuntu et les distributions basées sur la compilation, comme dans cet exemple gentoo.
CGROUP et libcgroup
CGROUP (ou cgroup) est un ensemble de fonctions des noyaux récents. Libcgroup est une bibliothèque de fonctions et un ensemble de programmes qui permettent de gérer facilement ces fonctions.CGROUP fournit un mécanisme d'agrégation / partitionnement des ensembles de tâches, et de tous leurs futurs enfants, en groupes hiérarchiques ayant un comportement spécialisé. Le patch temps réel du kernel ne fait pas autre chose: il permet de définir une priorité supérieure aux tâches du groupe audio. Nous pouvons faire la même chose avec CGROUP, ce avec n'importe quel kernel récent.
Il est possible de gérer ces hiérarchies et ces sous-systèmes avec des commandes depuis une console, mais libcgroup permet de le faire plus facilement, de façon plus étendue, et de rendre cette gestion permanente en modifiant sa configuration.
Le but de tout ça ? 🙄, je comparerais avec udev. Udev permet de gérer les périphériques de façon automatique (en principe ça marche assez bien heureusement ! ).
Cgroup fait la même chose mais avec toutes les tâches du système.
Le principe de base est d'assigner des ressources aux tâches.
Lors de sa mise en œuvre, je me suis rendu compte que bien que cgroup concerne l'ensemble des tâches et des ressources du système, il est, en tout cas pour ce qui nous intéresse ici, l'audio professionnelle, bien plus simple à configurer que udev. Ceci va faire plaisir à beaucoup de monde, j'en suis sûr ! 🎅
Sur le long terme, je pense que beaucoup d'entre nous utiliseront, pour l'audio pro, un kernel standard avec Cgroup. Cependant, le kernel temps réel ne va pas disparaitre, ceci car il a prouvé qu'il est une bonne solution, les développeurs du patch temps réel vont continuer à développer / expérimenter de nouvelles solutions, et aussi parce que Cgroup ajoute une légère surcharge et certains d'entre nous ne voudront pas, de ce fait, l'utiliser.
Configuration du noyau
Nous n'avons besoin que d'une seule fonction de Cgroup, son planificateur temps réel. Pour un kernel 3.6.2-gentoo:Copy to clipboard
General setup ---> [*] Control Group support ---> [*] Group CPU scheduler ---> [*] Group scheduling for SCHED_RR/FIFO
Cette dernière option nous donne CONFIG_RT_GROUP_SCHED, ce qui nous permet d'allouer la bande passante processeur à des groupes de tâches. Elle va aussi rendre impossible aux utilisateurs non root d'utiliser des tâches temps réel, ceci tant que la bande passante temps réel pour ces tâches n'a pas été allouée.
Ne chercher pas cette option dans un kernel temps-réel, elle n'existe pas pour le moment (3.6.3-rt8). De plus, je doute qu'elle n'y figure jamais car nous nous retrouverions avec deux options concurrentes pour faire la même chose.
Il n'est pas nécessaire de sélectionner "Automatic proocess group scheduling" car cela sélectionne d'autres options dont nous n'avons pas besoin et qui ne servent à rien avec RT_GROUP_SCHED.
Installation et configuration de libcgroup
Installation
gentoo :Sous gentoo, c'est aussi simple que
Copy to clipboard
emerge -a libcgroup
Autres distributions :
À compléter...
Configuration
Libcgroup vient avec deux Démons (programme qui tournent en tâche de fond) qui doivent être configurés et lancés lors du démarrage du système. Il n'existe pas de configuration par défaut, ceci car contrairement à UDEV qui prend en charge les périphériques existants de l'ordinateur, il est impossible de savoir quel usage veut faire l'utilisateur de son ordinateur, et par conséquent quelle optimisation lui convient.Ces deux démons sont cgconfig et cgred. Cgconfig monte le système de fichiers associé à cgroup. Cgred gère les ressources attribuées aux programmes gérés par crgoup.
Sous gentoo, ces deux daemons se trouvent dans /etc/init.d.
Quid d'autres distributions ?
Il faut éditer deux fichiers pour configurer cgroup. Le premier, /etc/cgroup/cgconfig.conf permet de définir les hiérarchies et les sous-systèmes associés à ces hiérarchies. Dans notre cas, nous définissons la hiérarchie cpu et le sous-système rtaudio en suivant les indications du ? wiki de JACK. J'ai d'abord essayé la méthode 2, mais cgconfig plantait au démarrage. La méthode 3 fonctionne bien.
/etc/cgroup/cgconfig.conf
Copy to clipboard
namespace { cpu = /; } group rtaudio { perm { task { uid = root; gid = audio; } admin { uid = root; gid = root; } } cpu { cpu.rt_runtime_us = 900000; } }
Nous définissons ici un groupe cgroup rtaudio. Il utilise la hiérarchie cpu. Nous l'utilisons pour définir le temps processeur que les processus temps-réel des programmes membres de ce groupe peuvent utiliser.
L'utilisateur root peut l'administrer (lancer des commandes depuis la console pour le modifier).
Les utilisateurs membres du groupe audio en font partie et peuvent l'utiliser. C'est le groupe dédicacé pour l'audio avec jack. D'autres distributions peuvent utiliser un autre groupe, il vous faut alors remplacer audio par le nom de ce groupe dans toutes les configurations de cette page.
La ligne avec cpu.rt_runtime_us définit le nombre de micro secondes par seconde que le processeur peut consacrer aux tâches temps-réel du groupe rtaudio, ici 900'000. Il reste donc au minimum 100'000 micro secondes par seconde disponibles pour les autres tâches.
La valeur de sched_rt_period_us est définie par le kernel (il est possible de la changer mais c'est inutile ici) et elle détermine la période considérée. Sa valeur est de 1 seconde. Les 100'000 micro secondes par seconde sont donc la différence entre sched_rt_period_us et cpu.rt_runtime_us. Avant, j'avais mis 950'000 micro secondes, mais en y regardant de plus près, je me suis rendu compte que cette dernière valeur est aussi la valeur de sched_rt_runtime_us du système, valeur que vous pouvez trouver avec
Copy to clipboard
# cat /proc/sys/kernel/sched_rt_runtime_us 950000 # cat /proc/sys/kernel/sched_rt_period_us 1000000
La différence est de 50'000, et comme l'indique la documentation du kernel, le kernel a besoin de ces 50'000 micro secondes pour assurer le bon fonctionnement des autres tâches. Mais le kernel contient aussi des tâches temps réel. Avec cette configuration, nous nous retrouvons donc avec deux groupes qui peuvent lancer des tâches temps-réel : le kernel et rtaudio. Il m'a donc semblé important, afin d'assurer le bon fonctionnement du kernel, de lui laisser plus de temps à disposition qu'à rtaudio. En fait je n'en suis pas sur, et donc je préfère être prudent.
Ainsi, une tâche temps réel qui monopolise le processeur se verra obligée de laisser la main aux tâches temps réel du noyau pendant les 50'000 micro secondes de différence entre sched_rt_runtime_us et cpu.rt_runtime_us. Elle ne devrait donc pas pouvoir planter le système.
Enfin, cpu.rt_runtime_us ne concerne que les processus temps-réel d'un programme. Par exemple dans ardour, seul le traitement audio sera concerné. Les autres processus d'ardour comme l'interface graphique seront dans les 100'000, ils bénéficieront donc d'une priorité beaucoup moins grande.
Le second fichier est /etc/cgroup/cgrules.conf
Il est utilisé pour définir les programmes qui font partie du cgroup rtaudio. En d'autres termes, c'est là que nous allouons la bande passante temps-réel pour les programmes.
Une modification de JACK est en cours de développement pour permettre à jackd-jackdbus de rajouter automatiquement à cgroup temps-réel les programmes qui utilisent JACK. Mais c'est un travail en cours, donc nous devons rajouter tous les programmes souhaités :
Copy to clipboard
@audio:jackd cpu rtaudio/ @audio:jackdbus cpu rtaudio/ @audio:ardour cpu rtaudio/ @audio:mplayer cpu rtaudio/
Une des deux premières lignes est indispensable, elles rajoutent respectivement jackd et jackdbus.
Les deux suivantes rajoutent respectivement ardour et mplayer.
Il faut encore configurer PAM. Pour cela, nous définissons une priorité temps réel de 99 pour les tâches du groupe audio. Le groupe audio doit aussi n'avoir aucune restriction d'utilisation de la mémoire.
Dans le fichier /etc/security/limits.conf:
Copy to clipboard
@audio - rtprio 99 @audio - memlock unlimited
Bien sur, vous devez être membre du groupe audio.
Pour lancer les démons de Cgroup, tapez :
Copy to clipboard
/etc/init.d/cgred start * Starting cgconfig service ... [ ok ] * Starting CGroup Rules Engine Daemon ... [ ok ]
Nos deux démons ont bien été lancés. Pour les lancer automatiquement au démarrage :
Copy to clipboard
rc-update add cgred default
Test
Pour m'assurer que cgroup fonctionne bien et que les programmes que je lance fonctionnent comme souhaité, j'ai réalisé deux petits scripts que j'ai placé dans $PATH.Pour connaitre votre PATH :
Copy to clipboard
echo $PATH ~/bin:~/bin:/usr/local/bin:/usr/bin:/bin:/opt/bin:/usr/x86_64-pc-linux-gnu/gcc-bin/4.5.3:/usr/qt/3/bin:/usr/games/bin
Je les ai placés dans ~/bin
Notez aussi que les fichiers de la hiérarchie CGroup peuvent se trouver à un endroit différent que celui utilisé ici et propre à gentoo (/sys/fs/cgroup).
Le premier script, findrtp :
findrtp
Copy to clipboard
#!/bin/sh for i in `cat /sys/fs/cgroup/cpu//rtaudio/cgroup.procs`; do echo "Trouvé le pid $i qui correspond à `cat /proc/$i/cmdline`"; done
Il faut le sauver (ici sous ~/bin/findrtp) et le rendre exécutable :
Copy to clipboard
chmod +x findrtp
Ce programme trouve les processus du cgroup rtaudio et nous donne leurs pid et la ligne de commande correspondante :
Copy to clipboard
findrtp Trouvé le pid 3882 qui correspond à /usr/bin/jackdbusauto Trouvé le pid 11574 qui correspond à mplayerdvb://2@
Le deuxième script, findrtt :
findrtt
Copy to clipboard
#!/bin/sh for i in `cat /sys/fs/cgroup/cpu//rtaudio/tasks`; do echo "Trouvé le pid $i qui correspond à `cat /proc/$i/cmdline`"; done
Ce programme trouve toutes les tâches du cgroup rtaudio. Il est nécessaire car un processus (programme) peut avoir plusieurs tâches.
Il faut aussi le sauver et le rendre exécutable.
Copy to clipboard
findrtt Trouvé le pid 3882 qui correspond à /usr/bin/jackdbusauto Trouvé le pid 3889 qui correspond à /usr/bin/jackdbusauto Trouvé le pid 3890 qui correspond à /usr/bin/jackdbusauto Trouvé le pid 3891 qui correspond à /usr/bin/jackdbusauto Trouvé le pid 11574 qui correspond à mplayerdvb://2@ Trouvé le pid 11577 qui correspond à mplayerdvb://2@ Trouvé le pid 11578 qui correspond à mplayerdvb://2@ Trouvé le pid 11579 qui correspond à mplayerdvb://2@
Nous voyons avec findrtp que nous avons deux programmes temps réel, jackdbusauto et mplayer. Avec findrtt, nous voyons que chacun de ces programmes utilise 4 tâches. Mais nous ne savons pas encore lesquelles sont temps-réel. Pour cela, nous pouvons utiliser ps:
Copy to clipboard
ps -eLo rtprio,pri,cgroup,class,pid,pcpu,%mem,user,comm --sort pri|less RTPRIO PRI CGROUP CLS PID %CPU %MEM USER COMMAND ... - 19 2:cpu:/rtaudio TS 2613 0.0 1.0 dom jackdbus - 19 2:cpu:/rtaudio TS 2613 0.0 1.0 dom jackdbus - 19 2:cpu:/rtaudio TS 2613 0.0 1.0 dom jackdbus 10 50 2:cpu:/rtaudio FF 2613 0.4 1.0 dom jackdbus - 19 2:cpu:/rtaudio TS 2613 0.0 1.0 dom jackdbus ... - 19 2:cpu:/rtaudio TS 3642 0.0 1.0 dom alsa_out - 19 2:cpu:/rtaudio TS 3642 0.0 1.0 dom alsa_out - 19 2:cpu:/rtaudio TS 3642 0.0 1.0 dom alsa_out 5 45 2:cpu:/rtaudio FF 3642 0.5 1.0 dom alsa_out - 19 2:cpu:/rtaudio TS 3643 0.0 1.0 dom alsa_in - 19 2:cpu:/rtaudio TS 3643 0.0 1.0 dom alsa_in - 19 2:cpu:/rtaudio TS 3643 0.0 1.0 dom alsa_in 5 45 2:cpu:/rtaudio FF 3643 0.5 1.0 dom alsa_in - 19 2:cpu:/rtaudio TS 3664 0.0 1.3 dom timidity - 19 2:cpu:/rtaudio TS 3664 0.0 1.3 dom timidity - 19 2:cpu:/rtaudio TS 3664 0.0 1.3 dom timidity 5 45 2:cpu:/rtaudio FF 3664 0.0 1.3 dom timidity - 19 2:cpu:/rtaudio TS 30170 6.1 1.4 dom mplayer - 19 2:cpu:/rtaudio TS 30170 0.0 1.4 dom mplayer - 19 2:cpu:/rtaudio TS 30170 0.0 1.4 dom mplayer 5 45 2:cpu:/rtaudio FF 30170 0.1 1.4 dom mplayer
Ceci nous montre entre autre quelles sont les tâches du cgroup rtaudio, leur priorité, leur priorité temps réel, ainsi que leur classe d'agencement. TS est l'agencement "normal" SCHED_OTHER, FF est l'agencement temps-réel SCHED_FIFO.
Un autre test est de baisser la latence de jack. Lancez qjackctl et jouez avec les paramètres. Ainsi, avec les Control Groups, il m'a été possible de baisser la latence de jack avec le kernel gentoo de 42,7 msec (1024 Frames/Period, 48kHz, 2 Periods/Buffer) à 0,667 msec (16 Frames/Period) sans avoir plus de xruns (seulement au lancement des applications), soit un résultat aussi bon qu'avec un kernel temps-réel.
Il y a aussi htop qui nous donne les même renseignements que top, mais avec une autre présentation:
htop est configuré (avec F2) pour montrer tous les threads ainsi que la collone Cgroup. Avec F6, l'affichage est trié par ordre de priorité descendante. Nous voyons 5 threads du kernel qui ont la priorité la plus haute (RT - temps-réel). Ensuite viennent le thread temps-réel de jack avec une priorité de -11 ainsi que les autres threads temps réel des programmes connectés à jack avec une priorité de -6. Seulement ensuite viennent tous les autres threads.
Pour bien charger le système, j'ai lancé l'installation/compilation de hugin. Les 4 processeurs sont à 100% d'utilisation, beaucoup de mémoire est utilisée, et nous ne voyons pas de xruns dans l'icône de qjackctl en bas à gauche.
Note:
das_watchdog
das_watchdog ne sert plus à rien quand CGroup est configuré pour utiliser son agenceur temps-réel. Ceci vient du fait que cet agenceur lui fait croire que tout va bien. En fait, c'est cet agenceur temps réel de CGroup qui fait le travail de das_watchdog et ce dernier n'a donc jamais à intervenir. Vous pouvez donc enlever das_watchog de votre système.Liens
Problème entre JACK et le noyau des versions récentes d'Ubuntu (10.10 et 11.X)redhat: Using Control Groups
Documentation du kernel linux sur les cgroups
Some notes on CGroups
JACK and RT cgroups
How do I configure my linux system to allow JACK to use realtime scheduling?
limits.conf(5) - Linux man page