3IS - Système d`exploitation linux - Processus - Etis

Commentaires

Transcription

3IS - Système d`exploitation linux - Processus - Etis
3IS - Système d'exploitation linux
Processus
2010 – David Picard
Contributions de : Arnaud Revel, Mickaël Maillard
[email protected]
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Définitions
instructions
programme
tâche
processus
système
●
●
●
Un programme est un ensemble d'instructions
Une tâche est un programme pourvu de la structure système
nécéssaire à son exécution (statique)
Un processus est un tâche en cours d'exécution (dynamique)
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
États d'un processus
●
●
●
●
TASK_RUNNING : en cours dexécution ou en
attende d'être exécuté
TASK_INTERRUPTIBLE : suspendu en attente
d'une condition (interruption matérielle, signal, …
)
TASK_ZOMBIE : exécution terminée, mais le
processus parent n'a pas réclamé les
informations sur son fils
TASK_DEAD : état final, en cours de
suppression par le système
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Cycle de vie
Zombi
Zombi
Nouveau
Nouveau
(transitoire)
(transitoire)
Actif
Actif
(mode
(modeuser)
user)
Éligible
Éligible
résident
résident
Éligible
Éligible
Swappé
Swappé
Actif
Actif
(mode
(modenoyau)
noyau)
Endormi
Endormi
résident
résident
Endormi
Endormi
Swappé
Swappé
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Cycle de vie
Nouveau
Nouveau
(transitoire)
(transitoire)
Zombi
Zombi
fork
Actif
Actif
(mode
(modeuser)
user)
Éligible
Éligible
résident
résident
Éligible
Éligible
Swappé
Swappé
Actif
Actif
(mode
(modenoyau)
noyau)
Endormi
Endormi
résident
résident
Endormi
Endormi
Swappé
Swappé
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Cycle de vie
Nouveau
Nouveau
(transitoire)
(transitoire)
Zombi
Zombi
préemption
Éligible
Éligible
résident
résident
Éligible
Éligible
Swappé
Swappé
Actif
Actif
(mode
(modeuser)
user)
exécution
Actif
Actif
(mode
(modenoyau)
noyau)
Endormi
Endormi
résident
résident
Endormi
Endormi
Swappé
Swappé
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Cycle de vie
Zombi
Zombi
Nouveau
Nouveau
(transitoire)
(transitoire)
Actif
Actif
(mode
(modeuser)
user)
Éligible
Éligible
résident
résident
Éligible
Éligible
Swappé
Swappé
retour
Interruption
appel système
Actif
Actif
(mode
(modenoyau)
noyau)
Endormi
Endormi
résident
résident
Endormi
Endormi
Swappé
Swappé
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Cycle de vie
Zombi
Zombi
Nouveau
Nouveau
(transitoire)
(transitoire)
Actif
Actif
(mode
(modeuser)
user)
Éligible
Éligible
résident
résident
Éligible
Éligible
Swappé
Swappé
wakeup
Actif
Actif
(mode
(modenoyau)
noyau)
Endormi
Endormi
résident
résident
sleep
Endormi
Endormi
Swappé
Swappé
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Cycle de vie
Zombi
Zombi
Nouveau
Nouveau
(transitoire)
(transitoire)
Actif
Actif
(mode
(modeuser)
user)
terminaison
Éligible
Éligible
résident
résident
Éligible
Éligible
Swappé
Swappé
Actif
Actif
(mode
(modenoyau)
noyau)
Endormi
Endormi
résident
résident
Endormi
Endormi
Swappé
Swappé
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Cycle de vie
Zombi
Zombi
Nouveau
Nouveau
(transitoire)
(transitoire)
swap out
Éligible
Éligible
Swappé
Swappé
wakeup
Actif
Actif
(mode
(modeuser)
user)
Éligible
Éligible
résident
résident
swap in
Endormi
Endormi
Swappé
Swappé
Actif
Actif
(mode
(modenoyau)
noyau)
Endormi
Endormi
résident
résident
swap out
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Création de processus : fork()
Stack (données)
int main(int argc, char **argv)
{
int pid, status;
Adresses
pidfils = fork();
Data (données)
Text (code)
if(pidfils != 0)
{ /* code du père */
printf(“je suis le père %d et mon fils est %d\n”, getpid(), pidfils);
wait(&status);
}
else
{ /* code du fils */
printf(“je suis le fils %d\n”, getpid());
}
return 0;
}
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Création de processus : fork()
Stack (données)
int main(int argc, char **argv)
{
int pid, status;
Adresses
pidfils = fork();
Data (données)
Text (code)
PID : if(pidfils != 0)
Le PID { /* code du père */
est un nombre identifiant
chaque processus.
Il est unique.
printf(“je suis le père %d et mon Il est
attribué par le système.
fils est %d\n”, getpid(), pidfils);
wait(&status);
}
else
{ /* code du fils */
printf(“je suis le fils %d\n”, getpid());
}
return 0;
}
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Création de processus : fork()
Stack (données)
int main(int argc, char **argv)
{
int pid, status;
Adresses
pidfils = fork();
Data (données)
Text (code)
if(pidfils != 0)
{ /* code du père */
printf(“je suis le père %d et mon fils est %d\n”, getpid(), pidfils);
wait(&status);
}
else
{ /* code du fils */
printf(“je suis le fils %d\n”, getpid());
}
return 0;
}
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Appel système fork()
●
Copie le processus courrant
●
Sont hérités :
–
–
–
–
–
●
les variables initialisées
l’environnement
les fichiers ouverts
le traitement des signaux
le GID (Group IDentifier)
Ne sont pas hérités :
–
–
Le PID (un nouveau est attribué)
Le PPID (Parent PID)
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
fork()
Création de processus : fork()
int main(int argc, char **argv)
{
Pour le processus père, fork()
renvoie le pid du fils, différent de int pid, status;
0.Stack (données)
Adresses
pidfils = fork();
if(pidfils != 0)
Pour le processus fils, fork() { /* code du père */
printf(“je suis le père %d et mon renvoie 0.
fils est %d\n”, getpid(), pidfils);
Data (données)
wait(&status);
}
else
{ /* code du fils */
Text (code)
printf(“je suis le fils %d\n”, getpid());
}
return 0;
}
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Création de processus : fork()
Stack (données)
int main(int argc, char **argv)
{
int pid, status;
Adresses
pidfils = fork();
getpid() renvoie le pid du
processus courrant. if(pidfils != 0)
Data (données)
Text (code)
{ /* code du père */
printf(“je suis le père %d et mon fils est %d\n”, getpid(), pidfils);
wait(&status);
}
else
{ /* code du fils */
printf(“je suis le fils %d\n”, getpid());
}
return 0;
}
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Création de processus : fork()
Adresses
Stack (données)
int main(int argc, char **argv)
{
int pid, status;
wait() met le processus
courrant en attente. Quand le fils
se termine, un signal est envoyé
au père.
Data (données)
Text (code)
pidfils = fork();
if(pidfils != 0)
{ /* code du père */
printf(“je suis le père %d et mon fils est %d\n”, getpid(), pidfils);
wait(&status);
}
else
{ /* code du fils */
printf(“je suis le fils %d\n”, getpid());
}
return 0;
}
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Code exécuté par le père et le fils
Père
int main(int argc, char **argv)
{
int pid, status;
Fils
int main(int argc, char **argv)
{
int pid, status;
pidfils = fork();
printf(“je suis le père %d et mon fils est %d\n”,getpid(), pidfils);
pidfils = fork();
printf(“je suis le fils %d\n”, getpid());
return 0;
wait(&status);
}
return 0;
}
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Remplacement de code : exec()
●
L'appel système exec() permet de remplacer le contenu de la zone de mémoire contenant le code du processus
–
Le pointeur de programme est placé au début de la zone de code.
–
Pour lancer un nouveau programme, il suffit de faire appel à fork() puis de remplacer le code du processus fils en appellant exec() dans la partie fils.
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Remplacement de code : exec()
int main(int argc, char **argv)
{
int pid, status;
pidfils = fork();
fork()
if(pidfils != 0)
{ /* code du père */
wait(&status);
}
else
{ /* code du fils */
printf(“je suis le fils %d\n”, getpid());
exec()
exec(“/usr/bin/ls”, “ls”, NULL);
printf(“ceci ne sera jamais affiché”);
}
return 0;
}
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Remplacement de code : exec()
Clonnage du
processus
courrant
int main(int argc, char **argv)
{
int pid, status;
pidfils = fork();
if(pidfils != 0)
{ /* code du père */
wait(&status);
}
else
{ /* code du fils */
printf(“je suis le fils %d\n”, getpid());
exec(“/usr/bin/ls”, “ls”, NULL);
printf(“ceci ne sera jamais affiché”);
}
return 0;
}
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Remplacement de code : exec()
int main(int argc, char **argv)
{
int pid, status;
pidfils = fork();
Remplacement du
code du fils par celui
contenu dans le fichier
“/usr/bin/ls”
if(pidfils != 0)
{ /* code du père */
wait(&status);
}
else
{ /* code du fils */
printf(“je suis le fils %d\n”, getpid());
exec(“/usr/bin/ls”, “ls”, NULL);
printf(“ceci ne sera jamais affiché”);
}
return 0;
}
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Remplacement de code : exec()
int main(int argc, char **argv)
{
int pid, status;
pidfils = fork();
Ce code ne sera jamais
exécuté, car il a été
remplacé par celui de
ls
if(pidfils != 0)
{ /* code du père */
wait(&status);
}
else
{ /* code du fils */
printf(“je suis le fils %d\n”, getpid());
exec(“/usr/bin/ls”, “ls”, NULL);
printf(“ceci ne sera jamais affiché”);
}
return 0;
}
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Structures associées
●
À chaque processus est associé :
●
●
Un contexte utilisateur : le processus tel que vu par
l'utilisateur
Un contexte Système : le processus tel que vu par
le noyau, décomposé en deux parties
–
–
Un descripteur de processus
Une pile système
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Structures associées
Mode user
Mode noyau
Descripteur
De
processus
Data (données)
Text (code)
stack
Pile système
Adresses
Stack (données)
thread_info
task
thread_info
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Descripteur de processus
●
Structure de type task_struct qui contient
–
–
–
–
●
Des informations sur le processus (pid, état, …)
Des informations sur ses relations parent/enfant
Des informations sur les fichiers ouverts
…
Pour gérer les processus, le noyau dispose
d'une liste doublement chainée de task_struct
–
L'accès à un descripteur de processus peut aussi être fait
au moyen d'une table de hachage ayant pour clés les
PID
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Descripteur de processus du noyau 0.01
struct task_struct {
/* these are hardcoded ­ don't touch */
long state; /* ­1 unrunnable, 0 runnable, >0 stopped */
long counter;
long priority;
long signal;
fn_ptr sig_restorer;
fn_ptr sig_fn[32];
/* various fields */
int exit_code;
unsigned long end_code,end_data,brk,start_stack;
long pid,father,pgrp,session,leader;
unsigned short uid,euid,suid;
unsigned short gid,egid,sgid;
long alarm;
long utime,stime,cutime,cstime,start_time;
unsigned short used_math;
/* file system info */
int tty; /* ­1 if no tty, so it must be signed */
unsigned short umask;
struct m_inode * pwd;
struct m_inode * root;
unsigned long close_on_exec;
struct file * filp[NR_OPEN];
/* ldt for this task 0 ­ zero 1 ­ cs 2 ­ ds&ss */
struct desc_struct ldt[3];
/* tss for this task */
struct tss_struct tss;
};
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Pile système
●
Sert à stocker le contexte matériel du
processus
–
–
–
–
On appelle contexte matériel l'ensemble des données
contenues dans les registres nécéssaire à l'exécution du
processus
Les processus ne peuvent pas partager les registres,
lorsqu'un changement de processus survient, le contexte
matériel est sauvegardé dans la pile système.
Lorsque le processus est de nouveau actif, le contexte
matériel est restauré depuis la pile
Le descripteur de processus contient un pointeur vers la
pile système
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Union thread_union
●
●
●
La pile système est un
espace de 2 pages
stack
Elle contient une structure
thread_info à son
extrémité basse
thread_info contient un
pointeur vers le
thread_info
descripteur de processus
ainsi qu'un espace de
stockage pour
sauvegarder certainsunion thread_union {
struct thread_info thread_info;
registres
Pointeur
de pile
Descripteur
de processus
unsigned long stack[THREAD_SIZE/sizeof(long)];
};
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Ordonnancement
●
●
Le système est multi-tâches : plusieurs
processus s'exécutent en même temps
La simultanéité est simulé par un partage du
temps de calcul
–
–
–
On stope l'exécution d'un processus pour en exécuter un
autre
Le temps est découpé en quantas
Les quantas sont attribués aux processus en cours
d'exécution
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Ordonnancement
●
Le passage d'un processus à un autre est appelé
commutation de processus
–
–
●
La commutation est déclanchée par l'interruption 0,
générée par l'horloge, généralement toutes les 10ms
–
●
Dans le cas du multitâches coopératif, la commutation est initiée
par les programmes eux-mêmes
Dans le multitâches préemptif (cas de Linux), des évènements
externes force la commutation
Cette interruption appelle la fonction schedule()
Certains processus sont plus prioritaires que
d'autre lors de l'ordonnancement
–
En fonction de la valeur de priorité dans la task_struct
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Fonction schedule()
void schedule(void)
{
int i,next,c;
struct task_struct ** p;
/* check alarm, wake up any interruptible tasks that have got a signal */
for(p = &LAST_TASK ; p > &FIRST_TASK ; ­­p)
if (*p) {
if ((*p)­>alarm && (*p)­>alarm < jiffies) {
(*p)­>signal |= (1<<(SIGALRM­1));
(*p)­>alarm = 0;
}
if ((*p)­>signal && (*p)­>state==TASK_INTERRUPTIBLE)
(*p)­>state=TASK_RUNNING;
}
/* this is the scheduler proper: */
while (1) {
c = ­1;
next = 0;
i = NR_TASKS;
p = &task[NR_TASKS];
while (­­i) {
if (!*­­p)
continue;
if ((*p)­>state == TASK_RUNNING && (*p)­>counter > c)
c = (*p)­>counter, next = i;
}
if (c) break;
for(p = &LAST_TASK ; p > &FIRST_TASK ; ­­p)
if (*p)
(*p)­>counter = ((*p)­>counter >> 1) +
(*p)­>priority;
}
switch_to(next);
}
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Commutation de processus
●
●
●
Un processus est associé à un contexte
matériel particulier, nécéssaire au bon
déroulement de sont exécution
Lors d'une commutation de processus, le
noyau doit sauvegarder le contexte du
processus sortant
Puis il doit restaurer le contexte du processus
entrant
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Macro switch_to (simplifiée)
Imaginons deux processus prev et next :
1. Sauve les pointeurs de prev et next dans deux registres
2. Sauve EBP (frame pointer) dans la pile noyau de prev
3. Sauve ESP (stack pointer) dans la thread_info de prev
4. Charge next->thread.esp dans ESP (on travaille avec la pile de next)
5. Sauve l'adresse de l'étiquette 1 dans prev->thread.eip
6. Charge next->thread.eip dans EIP (instruction pointer) (exécution de next)
7. EIP contient logiquement l'adresse de l'étiquette 1 qui est alors exécutée :
1:
­ charge EBP depuis la pile noyau
­ charge EFLAGS depuis la pile
8. Retour au code de next
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Algorithmes d'ordonnancement
●
Dans le noyau 0.01
–
La task_struct définie deux champs : priority
et counter
–
Les processus sont initialisés avec une priority de
15
–
À chaque tick d'horloge, schedule est appelé
–
counter est alors décrémenté
–
Le processus avec le counter le plus élevé est
sélectionné
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Tourniquet
●
Les procéssus sont considérés comme ayant la
même priorité
–
–
–
–
●
Ils sont rangés dans une liste
Le processus en tête de liste est sélectionné
Un quanta de temps lui est octroyé
Il est remis en queue de liste
Linux utilise cet ordonnanceur pour les
processus temps réels
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Tourniquet avec priorités
●
●
●
Les processus sont organisés par listes de
priorité
On séléctionne les liste par ordre de priorité
On applique un tourniquet au sein de la liste
sélectionnée
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Ordonnanceur en O(1)
●
●
L’ordonnanceur en O (1) a ete utilise du noyau experimental 2.5.2
(janvier 2002) jusqu’au noyau 2.6.22 (octobre 2007)
Cet ordonnanceur a ete developpe par Ingo Molnar pour prendre
en compte plusieurs remarques par rapport aux ordonnanceurs
precedents
–
–
–
–
–
–
Le temps accorde au scheduling doit dependre faiblement de la charge
La reactivite du systeme doit etre privilegiee pour les processus
En interaction avec l’utilisateur
L’ordonnanceur doit tendre vers le “temps reel”
L’ordonnanceur doit prendre en compte le contexte
multi-processeurs
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Ordonnanceur en O(1)
●
Pour répondre a ces critères, l’ordonnanceur
differencie
–
–
●
Des processus temps réel ordonnancés à part
Des processus conventionnels
Au sein des processus conventionnels deux
sous-catégories sont aussi identifiées
–
–
Les processus interactifs
Les processus tournant en tache de fond
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Ordonnanceur en O(1)
●
Ils correspondent au plages de priorités les plus
élevées (0 a 99)
–
–
●
Un processus temps-réel est toujours consideré comme actif
Un processus d’une priorite donnée s’exécute forcement
avant un processus temps-réel de priorité inférieure
Dans une file de priorité, ils sont ordonnancés
suivant 2 politiques
–
–
SCHED_FIFO : même si d’autres processus temps-réel de
même priorité sont dans la file et si aucun processus de
priorité supérieure n'est présent, le processus reste actif
autant de temps qu’il le désire
SCHED_RR : c'est le “Round Robin” qui est utilisé
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Processus conventionnels
●
La classification interactif/batch s’effectue en
fonction de l’historique du processus et en
particulier de son temps d’endormissement
moyen
–
–
●
Un processus qui dort souvent est favorisé par le scheduler
En effet, un tel processus est souvent un processus qui
accède à des ressources bloquantes ou un processus qui
ne se comporte pas de façon égoïste en consommant toute
la tranche de temps qui lui a été allouée
Heuristique complexe de calcul de bonus afin de
déterminer la classe interactif/batch
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Completely Fair Scheduler (CFS)
●
Écrit en réponse à de critiques de l'ordonnanceur en O(1) par
rapport à la monté en charge, en particulier dans le contexte
multi-processeur
–
–
–
L'ordonnanceur O(1) utilise le temps moyen d'endormissement. Cependant,
des processus qui s'endorment souvent peuvent être des processus qui
accèdent beaucoup aux ressources et qui peuvent ainsi être à l'origine de réordonnancement fréquents
L'évaluation de l'interactivité des processus est faussée quand le système est
chargé. Les statistiques d'endormissement ne peuvent être fiables que s'il y a
suffisamment d'échantillons pour les calculer. Les processus interactifs
peuvent temporairement être considérés comme gros consommateurs de
CPU ce qui peut augmenter leur temps de latence
Certaines attaques du scheduler étaient facilement réalisables
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Principe
●
Le CFS considère un processeur multitâche idéal
qui peut exécuter en même temps plusieurs
processus en leur donnant chacun une portion
équitable de la puissance du processeur
–
–
●
●
Dans le cas où un seul processus est ordonnancé, 100% du
processeur lui est alloué
Dans le cas de 2, 50% serait alloué à chacun
Sur un processeur réel, une tâche seulement peut
être exécutée
Pendant ce temps, les autres processus attendent
le CPU
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Algorithme
Le CSF trace le déséquilibre de ``fair-play'' au niveau de chaque processus
● Quand un processus attend le CPU, l'ordonnanceur calcule le temps qu'il
aurait dû avoir s'il avait été sur un processeur idéal en divisant le temps
d'attente (exprimé en nanosecondes) par le nombre total de processus en
attente
● La valeur résultante est le temps CPU auquel le processus a droit
● Cette valeur est utilisée dans un arbre rouge-noir pour trier les processus en
vue de l'ordonnancement
● Cela détermine aussi le quantum de temps alloué au processus avant d'être
préempté
● La priorité statique agit comme un coefficient de pondération qui favorise ou
pénalise le processus en amplifiant/réduisant l'écart de temps entre le temps
idéal et le temps réellement utilisé
●
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Gestion modulaire de
l'ordonnancement
●
●
●
Le noyau 2.6.23 introduit la modularisation de
l'ordonnancement
La notion de classe d'ordonancement (struct sched_class) est aussi introduite
Chaque classe est associée a des files d’attentes
specifiques gerées par des modules différents
–
–
Le scheduler principal (kernel/sched.c) délegue la gestion spécifique
aux modules impliqués
Les processus temps réels sont géres par kernel/sched_rt.c
–
“Completely Fair Scheduler” est associé a la gestion de type
SCHED_OTHER, SCHED_BATCH et au module kernel/sched_fair.c
–
Un module (sched_idletask.c) se charge de la gestion de la tache
“idle” sur chaque processeur
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Groupes d'ordonnancement
●
●
●
●
●
A partir du noyau 2.6.24, la notion d'équité du scheduler a été élargie à
l'équité entre utilisateurs
Soient 2 utilisateurs A et B faisant tourner respectivement 2 et 48 tâches
sur une même machine
La notion de groupe d'ordonnancement permet d'être équitable avec A et B
au niveau utilisateur (et non plus au niveau processus)
Dans notre exemple chaque utilisateur bénéficie pour lui tout seul de 50%
du temps CPU: ses 50% sont partagés entre ses 2 processus pour A et
entre ses 48 processus pour B
L'implémentation est directe puisqu'il s'agit simplement de chaîner les
ordonnanceurs CFS: un ordonannceur est associé à la liste des groupes
puis, au sein d'un groupe, un nouvel ordonnanceur est associé pour
répartir équitablement le temps CPU entre les tâches
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
Initialisation du système
Chargement noyau
Exécution du process 1
Construction du process 0
/etc/init et /etc/rc
Exécution du process 0
/etc/getty
/bin/login
Construction du process 1
root
user
shell
swapper
Mode noyau
Mode user
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS
start_kernel()
●
●
●
●
●
●
●
●
La fonction start_kernel() est appelée au démarrage du noyau
Elle initialise certaines fonctions du noyau (allocateurs mémoire,
ordonnanceurs, etc)
Elle créé le processus 0, appelé swapper (ou idle), à l'aide de la fonction
kernel_thread()
Elle initialise le descripteur de processus du swapper
Elle créé ensuite le processus 1, appelé init, à l'aide de la fonction
kernel_thread() en copiant le swapper
Init invoque exec() pour remplacer son code par celui du programme
d'initialisation (souvent appelé init aussi)
Init devient un processus tout à fait normal
Généralement, le code chargé dans init contient de quoi lancer tous les
programmes nécéssaire au bon fonctionnement du système (en utilisant
fork() et exec())
ÉCOLE NATIONALE SUPÉRIEURE DE L'ÉLECTRONIQUE ET DE SES APPLICATIONS

Documents pareils