Méthodologie de développement

Cet article aborde quelques méthodes qui peuvent être utiles pour programmer plus méthodiquement afin d'éviter de trop longues heures de gdb L'utilisation de gdb n'est absolument pas problématique, mais peut prendre du temps (surtout pour un kernel), temps qui peut être économisé grâce à une meilleur méthodologie.

Panic et assertions

Une fonction appelée panic est fournis avec le module stdio.h, sa signature est identique à printf mais va faire planter votre kernel après avoir écrit le message. Cette fonction est très utile quand elle est placée dans des branchements que vous juger illégaux et y associer un message clair, permettant d'identifier l'origine de l'erreur.

Typiquement, vous pouvez faire paniquer votre programme si celui-ci ne trouve plus de processus à exécuter lors de l'ordonnancement, chose qui n'est jamais censée arriver puisque idle devrait toujours être présent.

Une autre fonction est assert, celle-ci prend en premier argument un boolean indiquant (= false) si le programme doit paniquer, avec le message donné dans les arguments suivants. C'est par exemple utile pour vérifier des préconditions internes au code kernel.

Attention, ces fonctions sont très intéressantes mais doivent pas être utilisées pour avertir de problèmes aux programmes utilisateurs. Le kernel ne doit paniquer uniquement en dernier recours, quand une situation n'a pas d'intérêt à être sauvée.

Le code suivant montre un exemple d'utilisation d'une assertion:

1
2
3
4
5
6
7
/// Fonction interne permettant de libérer les resources
/// utilisées par un processus. 
/// Le processus donné ne doit pas être NULL.
void process_free(struct process *process) {
    assert(process != NULL, "process_free: given process is null\n");
    // [...]
}

Utiliser printf avec des macros

L'utilisation de printf est très utile dans notre kernel, principalement car les interruptions sont désactivés pendant l'exécution du kernel et que nous somme sur un système simple cœur. Cependant, son utilisation peut rapidement rendre la sortie verbeuse, il est donc important d'utiliser des constantes macros afin de rendre les printf optionnels à la compilation.

Il est également important d'écrire des messages clairs, et identifiant correctement l'origine d'un message et son emplacement. Par exemple, si on souhaite tracer l'exécution de nos fonctions manipulant les processus, il peut être intéressant d'afficher le nom ou le PID du processus appelant la fonction, ainsi que les paramètres données à la fonction.

Le code suivant montre un exemple d'utilisation pour la fonction exit:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// Ou 0 si on veut désactiver les printf.
#define PROCESS_DEBUG 1

void exit(int code) {

#if PROCESS_DEBUG
    printf("[%s] exit(%d)\n", actif->name, code);
#endif

    // [...]

}

<