corectionsujets
This commit is contained in:
@@ -62,7 +62,7 @@ Ce « challenge » est une série d’exercices de programmation du noyau Linux,
|
||||
|
||||
Retirer les petites roues et construire son propre noyau. Plus question de s’appuyer sur des versions précompilées.
|
||||
|
||||
Pour cette tâche, lancer son propre noyau — et utiliser Git.
|
||||
Pour cette tâche, il faut faire tourner son propre noyau — et utiliser Git. « Exciting, right? No? Well... okay. »
|
||||
|
||||
### À faire
|
||||
|
||||
@@ -90,7 +90,7 @@ Créer un module noyau « Hello World » avec le comportement suivant. Bloc reco
|
||||
%
|
||||
```
|
||||
|
||||
Le module doit compiler sur n’importe quel système. Le sujet signale que c’est un indice de compatibilité de version.
|
||||
Attention : le module doit compiler sur n’importe quel système. Le PDF marque l’indice ainsi : `(<– version compatibility hint)`.
|
||||
|
||||
### À rendre
|
||||
|
||||
@@ -111,45 +111,50 @@ Chaînes exactes : `Hello world!`, `Cleaning up module.`, fichier `main.ko`.
|
||||
|
||||
## VIII. Assignment 03
|
||||
|
||||
Modifier le fichier C suivant pour qu’il respecte le style de code Linux (`Documentation/CodingStyle`).
|
||||
Bien joué d’être arrivé jusque-là. Le sujet espère qu’on s’amuse encore. On s’ennuie un peu, à force de seulement booter et installer des noyaux ?
|
||||
Alors il est temps de quelque chose de plus pédant — histoire de rappeler à quel point ces compilations de noyau sont amusantes.
|
||||
|
||||
### À faire
|
||||
|
||||
- Modifier le fichier C suivant pour qu’il respecte le style de code Linux (voir `Documentation/CodingStyle`).
|
||||
|
||||
### À rendre
|
||||
|
||||
- La version mise à jour du fichier C.
|
||||
|
||||
Capture [C4](captures/04-little-penguin-assignment-03-11.png). Transcription (l’indentation du PDF est la référence visuelle) :
|
||||
Le fichier est sur la page suivante. Capture [C4](captures/04-little-penguin-assignment-03-11.png). La transcription garde les décalages d’indentation de l’extraction du PDF : ils font partie du fichier à corriger. Si un espace diverge, la capture fait foi.
|
||||
|
||||
```c
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
int do_work(int *my_int, int retval) {
|
||||
int x;
|
||||
int y = *my_int;
|
||||
int z;
|
||||
|
||||
for (x = 0; x < my_int; ++x)
|
||||
{
|
||||
udelay(10);
|
||||
}
|
||||
for (x = 0; x < my_int; ++x)
|
||||
{
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
if (y < 10)
|
||||
/* That was a long sleep, tell userspace about it */
|
||||
pr_info("We slept a long time!");
|
||||
if (y < 10)
|
||||
/* That was a long sleep, tell userspace about it */
|
||||
pr_info("We slept a long time!");
|
||||
|
||||
z = x * y;
|
||||
return z;
|
||||
return 1;
|
||||
z = x * y;
|
||||
return z;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int my_init(void)
|
||||
{
|
||||
int x = 10;
|
||||
|
||||
x = do_work(&x, x);
|
||||
return x;
|
||||
x = do_work(&x, x);
|
||||
return x;
|
||||
}
|
||||
|
||||
void my_exit(void)
|
||||
@@ -164,6 +169,9 @@ Chaîne exacte dans le code : `We slept a long time!`
|
||||
|
||||
## IX. Assignment 04
|
||||
|
||||
Tu as survécu au chaos du style de code — bien joué.
|
||||
Passons à quelque chose de plus « real », parce que le sujet devine qu’on commence à s’ennuyer.
|
||||
|
||||
### À faire
|
||||
|
||||
- Modifier le module de l’assignment 01 pour qu’il soit chargé automatiquement quand n’importe quel clavier USB est branché. Le déclencheur est l’outil de hotplug de l’espace utilisateur adapté à la distribution : `depmod`, `kmod`, `udev`, `mdev` ou `systemd`.
|
||||
@@ -178,10 +186,13 @@ Le sujet dit que ça a l’air simple et que c’est un peu piégeux. Indice : c
|
||||
|
||||
## X. Assignment 05
|
||||
|
||||
Bien joué pour le chargement automatique du module. Ces macros de hotplug peuvent être piégeuses, mais les maîtriser est utile, surtout dans du vrai développement noyau.
|
||||
En parlant de vrai développement — écrivons du code digne de ce nom.
|
||||
|
||||
### À faire
|
||||
|
||||
- Reprendre le module de l’assignment 01 et en faire un driver de périphérique caractère `misc`. L’interface misc est présentée comme un moyen simple de créer un périphérique caractère sans entrer dans sysfs et l’enregistrement de devices.
|
||||
- Le device misc est créé avec un numéro mineur dynamique. Pas de mineur statique réservé.
|
||||
- Reprendre le module de l’assignment 01 et en faire un driver de périphérique caractère `misc`. L’interface misc est un moyen très simple de créer un périphérique caractère sans s’emberlificoter dans sysfs et l’enregistrement de devices. Le sujet dit : « Trust me, it’s way easier this way! »
|
||||
- Le device misc est créé avec un numéro mineur dynamique. Inutile de s’acharner à réserver un mineur statique pour un module de test. Ce serait une corvée pour rien.
|
||||
- Implémenter `read` et `write`.
|
||||
- Le nœud doit apparaître dans `/dev/fortytwo`.
|
||||
- En lecture, le device retourne le login étudiant à l’appelant.
|
||||
@@ -197,6 +208,11 @@ Libellés exacts : `misc`, `/dev/fortytwo`, `invalid value`.
|
||||
|
||||
## XI. Assignment 06
|
||||
|
||||
Bien joué pour le driver misc — plutôt propre et simple, non ?
|
||||
Au moment où l’on croyait que le défi ne parlait que de code dans le noyau, on revient à un sujet précédent. Eh oui : reconstruire des noyaux.
|
||||
|
||||
Ça reflète la réalité. Les développeurs noyau passent souvent plus de temps à recompiler qu’à écrire du code nouveau. Ce n’est pas glorieux, mais c’est une compétence vitale.
|
||||
|
||||
### À faire
|
||||
|
||||
- Télécharger le dernier noyau linux-next. Il change tous les jours : prendre la version la plus récente. Le construire et booter dessus.
|
||||
@@ -205,16 +221,20 @@ Libellés exacts : `misc`, `/dev/fortytwo`, `invalid value`.
|
||||
|
||||
- Le log de boot du noyau.
|
||||
|
||||
Le sujet ne définit pas linux-next dans l’énoncé. C’est une partie du défi.
|
||||
Indice : la documentation du processus de développement dans `Documentation/development-process/`, dans l’arbre des sources. Le PDF répète cet indice une seconde fois, en plus long : cette lecture doit dire tout ce qu’on n’a jamais voulu savoir sur ce que font les développeurs du noyau Linux et comment ils le font.
|
||||
Qu’est-ce que le noyau linux-next ?
|
||||
Ça fait partie du défi.
|
||||
|
||||
Premier indice, recopié : consulter l’excellente documentation sur le processus de développement du noyau dans `Documentation/development-process/`, dans l’arbre des sources. C’est une bonne lecture — on y apprend beaucoup sur la façon de travailler des développeurs noyau.
|
||||
|
||||
Le PDF enchaîne un second indice, presque le même : il faudrait lire l’excellente documentation sur la façon dont le noyau Linux est développé, dans `Documentation/development-process/`, dans les sources elles-mêmes. C’est une très bonne lecture, et elle devrait dire tout ce qu’on n’a jamais voulu savoir sur ce que font les développeurs du noyau Linux, et comment ils le font.
|
||||
|
||||
## XII. Assignment 07
|
||||
|
||||
On reviendra à linux-next dans une tâche ultérieure : ne pas supprimer ce répertoire. (Dans ce PDF, aucune tâche après celle-ci ne revient explicitement à linux-next. Assignment 08 et 09 n’en parlent pas. La phrase est quand même dans le sujet.)
|
||||
On reviendra au noyau linux-next dans une tâche ultérieure, donc ne pas supprimer ce répertoire : on en aura encore besoin. Pour l’instant, assez de compilations de noyau. Écrivons davantage de code.
|
||||
|
||||
Cette tâche ressemble à l’assignment 05. L’interface cette fois est debugfs.
|
||||
Cette tâche ressemble à l’assignment 05, où l’on a créé un device misc. Cette fois, une autre interface entre l’utilisateur et le noyau : debugfs.
|
||||
|
||||
Le sujet rapporte une rumeur : le créateur de debugfs aurait dit que la seule règle est « There are no rules. »
|
||||
La rumeur dit que le créateur de debugfs aurait affirmé que la seule règle est : « There are no rules. » Le sujet propose de tester cette théorie.
|
||||
|
||||
La distribution doit monter debugfs sur `/sys/kernel/debug/`. Sinon, la monter avec la commande recopiée :
|
||||
|
||||
@@ -222,7 +242,7 @@ La distribution doit monter debugfs sur `/sys/kernel/debug/`. Sinon, la monter a
|
||||
mount -t debugfs none /sys/kernel/debug/
|
||||
```
|
||||
|
||||
L’option `CONFIG_DEBUG_FS` doit être activée dans le noyau.
|
||||
Il faut que ce soit activé dans le noyau avec l’option `CONFIG_DEBUG_FS`, parce qu’on en aura besoin pour cette tâche.
|
||||
|
||||
### À faire
|
||||
|
||||
@@ -241,7 +261,8 @@ L’option `CONFIG_DEBUG_FS` doit être activée dans le noyau.
|
||||
|
||||
## XIII. Assignment 08
|
||||
|
||||
Revenir au style de code.
|
||||
Bien joué pour cette tâche debugfs.
|
||||
On ralentit un peu, et on revient au style de code.
|
||||
|
||||
### À faire
|
||||
|
||||
@@ -254,58 +275,58 @@ Revenir au style de code.
|
||||
Encadré [C5](captures/05-little-penguin-assignment-08-17.png) : « But wait—what is this code supposed to do? »
|
||||
Suite : « That’s part of the challenge. Have fun figuring it out! »
|
||||
|
||||
Capture du code [C6](captures/05-little-penguin-assignment-08-18.png). Transcription :
|
||||
Capture du code [C6](captures/05-little-penguin-assignment-08-18.png). Transcription alignée sur l’extraction du PDF. Le numéro de page imprimé à côté de `module_init` n’appartient pas au code. Si un espace diverge, la capture fait foi.
|
||||
|
||||
```c
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
// Dont have a license, LOL
|
||||
MODULE_LICENSE("LICENSE");
|
||||
MODULE_AUTHOR("Louis Solofrizzo <louis@ne02ptzero.me>");
|
||||
MODULE_DESCRIPTION("Useless module");
|
||||
|
||||
static ssize_t myfd_read
|
||||
static ssize_t myfd_read
|
||||
(struct file *fp, char __user *user,
|
||||
size_t size, loff_t *offs);
|
||||
static ssize_t myfd_write(struct file *fp, const char __user *user,
|
||||
static ssize_t myfd_write(struct file *fp, const char __user *user,
|
||||
size_t size, loff_t *offs);
|
||||
|
||||
static struct file_operations myfd_fops = {
|
||||
.owner = THIS_MODULE, .read = &myfd_read, .write = &myfd_write
|
||||
static struct file_operations myfd_fops = {
|
||||
.owner = THIS_MODULE, .read = &myfd_read, .write = &myfd_write
|
||||
};
|
||||
|
||||
static struct miscdevice myfd_device = {
|
||||
.minor = MISC_DYNAMIC_MINOR,.name = "reverse",
|
||||
.fops = &myfd_fops };
|
||||
static struct miscdevice myfd_device = {
|
||||
.minor = MISC_DYNAMIC_MINOR,.name = "reverse",
|
||||
.fops = &myfd_fops };
|
||||
|
||||
char str[PAGE_SIZE];
|
||||
char *tmp;
|
||||
char str[PAGE_SIZE];
|
||||
char *tmp;
|
||||
|
||||
static int __init myfd_init
|
||||
(void) {
|
||||
int retval;
|
||||
int retval;
|
||||
|
||||
retval = misc_register(&(*(&(myfd_device))));
|
||||
return 1;
|
||||
retval = misc_register(&(*(&(myfd_device))));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void __exit myfd_cleanup
|
||||
(void) {
|
||||
}
|
||||
|
||||
ssize_t myfd_read
|
||||
(struct file *fp,
|
||||
char __user *user,
|
||||
size_t size,
|
||||
loff_t *offs)
|
||||
ssize_t myfd_read
|
||||
(struct file *fp,
|
||||
char __user *user,
|
||||
size_t size,
|
||||
loff_t *offs)
|
||||
{
|
||||
size_t t, i;
|
||||
char *tmp2;
|
||||
size_t t, i;
|
||||
char *tmp2;
|
||||
|
||||
/***************
|
||||
* Malloc like a boss
|
||||
@@ -319,18 +340,18 @@ ssize_t myfd_read
|
||||
return simple_read_from_buffer(user, size, offs, tmp, i);
|
||||
}
|
||||
|
||||
ssize_t myfd_write
|
||||
(struct file *fp,
|
||||
const char __user *user,
|
||||
size_t size,
|
||||
loff_t *offs) {
|
||||
ssize_t res;
|
||||
ssize_t myfd_write
|
||||
(struct file *fp,
|
||||
const char __user *user,
|
||||
size_t size,
|
||||
loff_t *offs) {
|
||||
ssize_t res;
|
||||
|
||||
res = 0;
|
||||
res = simple_write_to_buffer(str, size, offs, user, size) + 1;
|
||||
// 0x0 = '\0'
|
||||
str[size + 1] = 0x0;
|
||||
return res;
|
||||
res = 0;
|
||||
res = simple_write_to_buffer(str, size, offs, user, size) + 1;
|
||||
// 0x0 = '\0'
|
||||
str[size + 1] = 0x0;
|
||||
return res;
|
||||
}
|
||||
|
||||
module_init(myfd_init);
|
||||
@@ -343,6 +364,9 @@ Le nom du device dans ce fichier est `reverse`, pas `fortytwo`.
|
||||
|
||||
## XIV. Assignment 09
|
||||
|
||||
Ouf... Le sujet ne sait pas qui a écrit ce dernier fichier, mais quand même.
|
||||
Bref, on retourne écrire quelque chose de plus sensé.
|
||||
|
||||
### À faire
|
||||
|
||||
- Créer un module qui liste les points de montage du système, avec le nom associé.
|
||||
@@ -363,7 +387,9 @@ dev /dev
|
||||
|
||||
- Le code source du module et un Makefile.
|
||||
|
||||
Le sujet dit que ce n’est pas dur, mais que ça peut être piégeux. Il renvoie à la documentation sur les points de montage, le listage de répertoires, et le parcours de listes chaînées dans le noyau.
|
||||
Ce n’est pas une tâche dure, mais elle peut être piégeuse.
|
||||
Le sujet renvoie à la documentation sur les points de montage, le listage de répertoires, et le parcours de listes chaînées dans le noyau.
|
||||
Et surtout — s’amuser :)
|
||||
|
||||
## XV. Rendu et évaluation par les pairs
|
||||
|
||||
|
||||
Reference in New Issue
Block a user