Dans le cadre des critiques négatives de l'article d'essai «Développer un OC de type Microkernel Unix - Scheduler», j'ai décidé de
redémarrer la série d'articles, en tenant compte de certains commentaires. Maintenant, après avoir réalisé mon public cible, j'ai pu déplacer l'attention de mon genre vers ceux qui en ont vraiment besoin.
Réponses aux commentaires de l'article précédent.
Remarque 1. Le planificateur est trop simple.
Depuis la publication de l'article précédent, le code a beaucoup changé. Un noyau à part entière s'est formé, qui a cessé d'être micronucléaire. Il existe un support pour le disque RAM initial (système de fichiers du noyau), le support pour la mémoire virtuelle (MMU). Il est devenu possible pour le noyau d'écrire des programmes personnalisés. Il y avait des appels système et la bibliothèque clib (stdio, string). Ainsi, le shell /initrd/sh.elf est un programme distinct qui est analysé par le chargeur de démarrage elf et s'exécute en tant que processus.
Liste des commandes shell: exec <file.elf>, ps, kill, exit. Dans ce cas, le shell peut être lancé à partir du shell lui-même (démontrant le multitâche).
Remarque 2. Trop de magie dans les coulisses des didacticiels vidéo.
J'ai décidé de mettre en évidence le texte que j'explique actuellement. Il s'est également dirigé vers les débutants qui ont besoin d'éclaircissements et des choses les plus simples. Honnêtement, j'ai été surpris que les nouveaux arrivants qui n'ont aucune expérience en programmation s'intéressent à un sujet aussi complexe, bien que ce soit un péché à cacher, j'ai commencé par là. J'ai changé le parti pris d'expliquer mon système d'exploitation à expliquer comment écrire votre OC.
Remarque 3. Où est le lien vers
github ?
Maintenant, elle l'est. Dans la
description de la vidéo sur YouTube (oui, je veux que vous ne passiez pas par mes cours de vidéo, au moins jetez un œil à un œil).
Remarque 4. Nous devons commencer par l'assemblage en premier.
C'est ce que nous ferons.
Remarque 5. Vous n'écrivez rien mais faites simplement des commentaires.
Oui, c'était une erreur de parler tout de suite de quelque chose de grand. Nous allons maintenant nous déplacer étape par étape, progressivement, en commençant par le noyau Hello world le plus simple. Des didacticiels vidéo vous permettront de créer une image holistique du monde, et le code source sur le github vous plongera dans les détails.
Table des matières.
1. Construisez le système (make, gcc, gas). Démarrage initial (multiboot). Lancez (qemu). Bibliothèque C (strcpy, memcpy, strext).
2. Bibliothèque C (sprintf, strcpy, strcmp, strtok, va_list ...). Construction de la bibliothèque en mode noyau et en mode application utilisateur.
3. Le journal système du noyau. Mémoire vidéo Sortie vers le terminal (kprintf, kpanic, kassert).
4. Mémoire dynamique, un tas (kmalloc, kfree).
6. Organisation de la mémoire et gestion des interruptions (GDT, IDT, PIC, syscall). Exceptions
5. Mémoire virtuelle (répertoire de pages et table de pages).
6. Le processus. Planificateur Multitâche. Appels système (kill, exit, ps).
7. Le système de fichiers du noyau (initrd), elf et ses internes. Appels système (exec).
8. Pilotes de périphériques de caractères. Appels système (ioctl, fopen, fread, fwrite). Bibliothèque C (fopen, fclose, fprintf, fscanf).
9. Le shell en tant que programme complet pour le noyau.
10. Mode de protection de l'utilisateur (ring3). Segment d'état de la tâche (tss).
Allons-y. Partie 1. Construire le système et lancer
Dans l'article, je ne listerai que les
étapes clés . Pour une explication détaillée, reportez-vous au didacticiel vidéo de cet article.
Vous avez besoin de Linux. Nous collecterons de la bonne vieille marque. Afin de compiler le fichier exécutable du noyau, les indicateurs suivants sont nécessaires:
CC_FLAGS=-g -m32 -isystem $(IDIR) -I include -DKERNEL=1 -fno-stack-protector -Wall -Werror -fno-pie AS_FLAGS=-g --32 LD_FLAGS=-m elf_i386
En tant qu'émulateur matériel, installez l'émulateur qemu sous Linux. Nous allons exécuter notre noyau comme ceci:
qemu-system-i386 -kernel ./bin/kernel.elf
Il faudra également un petit script pour l'éditeur de liens. Il est nécessaire pour charger des sections à la bonne adresse et dans le bon ordre. Nous y indiquerons également le point d'entrée:
OUTPUT_FORMAT(elf32-i386) ENTRY(start) SECTIONS { . = 0x100000; .text : { *(.text) } .data : { *(.data) } .bss : { *(.bss) } }
Étant donné que le noyau sera chargé conformément à la spécification de démarrage multiple, l'en-tête sera requis au début de la section de code:
.code32 .text # multiboot spec .align 4 multiboot: .long 0x1BADB002 # magic .long 0x00 # flags .long -(0x1BADB002 + 0x00) # checksum. m+f+c should be zero
Il est recommandé de passer immédiatement à votre propre pile et de configurer une table de descripteurs globale. Définissez notre propre pile:
.bss .fill 8192,1 # 8Kb stack:
Écrivez un point d'entrée. Vous pouvez trouver la syntaxe de l'assembleur gnu inhabituelle. Une fois, j'ai également préféré la syntaxe Intel, puis après l'avoir goûté, en plongeant dans le code source Linux, j'ai complètement préféré la syntaxe AT & T. Pour moi, l'essentiel à retenir est qu'ils ont les opérandes opposés. Le reste sera intuitif.
start: cli movl $stack,%esp push %esp push %ebx /* address of struct multiboot_t */ call kernel_start /* should never return */ hlt
Ceci complète le code passe-partout. Le plaisir commence. Nous pouvons maintenant écrire le code en C. Et tout d'abord, nous allons définir le message d'accueil.
char *hello = "Hello world!"; int screen_size = 80 * 25;
Ensuite, nous écrivons le point d'entrée lui-même vers lequel le code assembleur transférera le contrôle:
/* * Api - Kernel entry point */ extern void kernel_start(struct multiboot_t* multiboot, void* kstack) { char *video = (char*)0xB8000; char buff[screen_size + 1]; video[screen_size] = '\0'; memset(buff, ' ', screen_size); strext(video, buff, 0x7); strext(video, hello, 0x7); }
Ici, nous affichons simplement le message à l'écran. En principe, vous pouvez copier complètement le code de la première leçon, car il s'agit d'un modèle et ne sera jamais modifié. Pour afficher quelque chose à l'écran, il vous suffit de l'écrire directement dans la mémoire vidéo, en complétant chaque caractère par un symbole d'attribut. Pour ce faire, vous aurez besoin de votre propre bibliothèque C, que nous écrirons nous-mêmes pour nos besoins. Il sera donc plus facile de contrôler le processus. Ainsi, par exemple, nous avons aujourd'hui à notre disposition 2 fonctions familières (strcpy, memcpy) et une de nos propres strext afin d'insérer un octet d'attribut après chaque caractère.
Conclusion
C'est tout pour aujourd'hui. Regardez le didacticiel vidéo et essayez de faire la même chose par vous-même. Si cela ne fonctionne pas, vous pouvez jeter un œil aux sources de la leçon sur le github. Lien vers
github dans la description du didacticiel vidéo:Littérature
1. James Molloy. Faites rouler votre propre système d'exploitation jouet UNIX-clone.
2. Dents. Assembleur pour DOS, Windows, Unix
3. Kalachnikov. L'assembleur est facile!
4. Tanenbaum. Systèmes d'exploitation. Mise en œuvre et développement.
5. Robert Love. Noyau Linux Description du processus de développement.