Skip to main content

Historique: CGroup

Aperçu de cette version: 58



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.

Sous Debian, le kernel standard propose les cgroups, mais pas cette option. Il est donc nécessaire de compiler son propre kernel. Utiliser le kernel standard à la place du rt. J'ai supprimé toutes les options cgroups existantes et fait comme ci-dessus.

Installation et configuration de libcgroup

Installation

gentoo :
Sous gentoo, c'est aussi simple que
Copy to clipboard
emerge -a libcgroup


Debian :
Copy to clipboard
sudo apt-get install cgroup-bin libpam-cgroup


Autres distributions :
A 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.
Sous Debian, ce script est dans /etc/cgconfig.conf.

/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
Sous Debian, /etc/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 2 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


Sous Debian, c'est un peu plus compliqué, car ils ont viré les scripts de démarrage pour les mettre dans la doc, mais sans les patchs Debian. Comme cela prendrait 3 pages pour expliquer tout ce qu'il faut faire pour récupérer et appliquer les patchs, le plus simple est de télécharger Image cgroup-config-debian.tar.gz

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 avec le rtaudio Control Group et 100% processeur
htop avec le rtaudio Control Group


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

Historique

Information Version
Wed 15 Jan 2014 21:28 Dominique typos 70
Afficher
Wed 15 Jan 2014 21:22 Dominique systèmd, mise à jour 69
Afficher
Sun 12 Jan 2014 16:16 Dominique re typo 68
Afficher
Sun 12 Jan 2014 16:16 Dominique re typo 67
Afficher
Sun 12 Jan 2014 16:14 Dominique typos 66
Afficher
Sun 12 Jan 2014 14:11 olinuxx typo et kernel->noyau 65
Afficher
Sun 12 Jan 2014 12:28 Dominique précision importante 64
Afficher
Sun 12 Jan 2014 12:20 Dominique typo 63
Afficher
Sun 12 Jan 2014 12:19 Dominique systemd, suite et FIN ! 62
Afficher
Tue 03 Sep 2013 12:53 Dominique 61
Afficher
Tue 03 Sep 2013 04:52 olinuxx correction liens 60
Afficher
Tue 03 Sep 2013 01:16 Dominique 59
Afficher
Tue 03 Sep 2013 01:01 Dominique 58
Afficher
Mon 02 Sep 2013 20:13 Dominique 57
Afficher
Mon 02 Sep 2013 18:35 Dominique 56
Afficher
Mon 02 Sep 2013 18:29 Dominique 55
Afficher
Fri 01 Mar 2013 00:42 xzu mise en page 54
Afficher
Wed 27 Feb 2013 20:12 utilisateur_anonyme2 53
Afficher
Fri 11 Jan 2013 13:58 Dominique 52
Afficher
Fri 11 Jan 2013 13:52 Dominique 51
Afficher
Fri 11 Jan 2013 13:30 Dominique 50
Afficher
Tue 13 Nov 2012 19:38 Dominique note: das_watchdog 49
Afficher
Sun 28 Oct 2012 13:31 Dominique 48
Afficher
Sun 28 Oct 2012 13:27 Dominique 47
Afficher
Sun 28 Oct 2012 13:17 Dominique 46
Afficher
Sun 28 Oct 2012 12:31 Dominique 45
Afficher
Sun 28 Oct 2012 12:12 Dominique 44
Afficher
Sun 28 Oct 2012 10:40 Dominique 43
Afficher
Sun 28 Oct 2012 10:29 Dominique 42
Afficher
Sun 28 Oct 2012 10:28 Dominique 41
Afficher
Thu 25 Oct 2012 20:13 Dominique 40
Afficher
Thu 25 Oct 2012 19:36 Dominique 39
Afficher
Thu 25 Oct 2012 19:35 Dominique 38
Afficher
Thu 25 Oct 2012 19:35 Dominique 37
Afficher
Wed 24 Oct 2012 20:51 Dominique précisions 36
Afficher
Wed 24 Oct 2012 20:43 Dominique meilleure intro 35
Afficher
Thu 17 mai 2012 17:22 pianolivier modif lien(s) interne(s) 34
Afficher
Sat 12 mai 2012 17:49 pianolivier 33
Afficher
Sat 12 mai 2012 17:47 pianolivier ajout intro 32
Afficher
Sat 12 mai 2012 16:23 olinuxx coquilles 31
Afficher
Sat 12 mai 2012 16:21 olinuxx coquilles 30
Afficher
Sat 12 mai 2012 16:17 olinuxx coquilles 29
Afficher
Sat 12 mai 2012 16:16 olinuxx coquilles 28
Afficher
Sat 12 mai 2012 13:43 pianolivier ptite correction 27
Afficher
Sat 12 mai 2012 13:42 pianolivier cohérence site-wide 26
Afficher
Sat 12 mai 2012 13:42 pianolivier suppression d'un lien externe doublon 25
Afficher
Sat 12 mai 2012 13:40 pianolivier +lien udev 24
Afficher
Sat 12 mai 2012 13:39 pianolivier mise en page 23
Afficher
Sat 12 mai 2012 13:37 pianolivier mise en page 22
Afficher
Sat 12 mai 2012 13:34 pianolivier améliorations diverses 21
Afficher
  • «
  • 1 (en cours)
  • 2