Salut à tous,
Dans le cadre d'un projet académique, nous sommes amenés à écrire un petit scheduler basique pour le noyau 2.6.33.
Le fonctionnement est très simple : il y a 5 listes de priorités et le scheduler exécute toujours les tâches qui sont contenues dans la première liste non vide (de la plus haute priorité à la plus faible). A l'intérieur d'une liste, les tâches sont exécutées en round-robin (chaque tâche obtient un certain nombre de slice) et lorsqu'une tâche a tourné un certain nombre de fois, elle est déplacée dans la prochaine liste de plus basse priorité.
J'ai donc écrit le scheduler sans trop de problème. Tout fonctionne comme ça doit pendant un certain temps. Par contre, tout d'un coup les tâches sont exécutées en mode FIFO (plus de round-robin à l'intérieur des listes).
Voici les structures que j'utilise (les constantes ne sont généralement que des entiers) :
Code c : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 struct dummy_rq { struct list_head list; struct task_struct *task; //priority list in which the task resides (linked with the 'list' attribute) int priority_list; //number representing the aging of a process. As this value reaches zero it //will have a lower priority inside the dummy scheduler int time_tick_age; int time_tick_age_init; //number of tick a process is allowed to stay running. Once this value reaches //zero, it will be added at the end of the queue so another one can be executed //by the cpu (round-robin) int time_tick_init; int time_tick; };
Code c : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 struct rq { struct dummy_rq dummy_rq_queues[NB_PRIORITY_QUEUES]; //... pleins d'autres attributs }
Et ici les principaux morceaux de code pour la récupération d'une tâche :
Code c : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 //récupère la prochaine tâche à exécuter (prend toujours la //première dans la première liste vide - les liste sont ordonnées) static struct task_struct *pick_next_task_dummy(struct rq *rq) { for (index=0 ; index<NB_PRIORITY_QUEUES ; ++index) { if (!list_empty(&rq->dummy_rq_queues[index].list)) { struct dummy_rq* dummy = list_first_entry(&rq->dummy_rq_queues[index].list, struct dummy_rq, list); return dummy->task; } } return NULL; }
Code c : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 //fonction appelées à chacke time slice du CPU. La tâche courante reste //un certain nombre de tick et puis est passée à la fin de la liste static void task_tick_dummy(struct rq *rq, struct task_struct *curr, int queued) { struct dummy_rq* current_task; current_task = _get_dummy(rq, curr); if (current_task == NULL) return; current_task->time_tick--; if (current_task->time_tick <= 0) { current_task->time_tick = current_task->time_tick_init; current_task->time_tick_age--; if (current_task->time_tick_age <= 0) { current_task->time_tick_age = current_task->time_tick_age_init; update_priority(rq, current_task, (current_task->priority_list)+1); } else { list_move_tail(¤t_task->list, &rq->dummy_rq_queues[current_task->priority_list].list); } } }
J'ai affiché à coup de printk ce qui se passait dans cette liste au bout d'un moment. Il semble que tout d'un coup la tâche retournée par pick_next_task_dummy soit toujours la même et ce malgré qu'elle ait été mise en fin de queue via list_move_tail dans la fonction task_tick_dummy... De plus, lorsque la tâche est enlevée de la queue (list_del), c'est bien la suivante qui s'exécute (mais toujours pas de round-robin).
Le plus bizarre est que ce problème n'apparait qu'après un certain temps (environ 10 min) après avoir booté le noyau. Avant ça, le scheduler fonctionne correctement !
Il y a probablement un truc que je comprends pas ou que j'utilise mal, donc si quelqu'un a une idée je suis preneur
Merci d'avance !









Répondre avec citation
Partager