Entwicklung eines monolithischen Unix-ähnlichen Betriebssystems - Erste Schritte (1)

Im Zusammenhang mit den negativen Bewertungen des Testartikels „Entwickeln eines Microkernel Unix-ähnlichen OC - Schedulers“ habe ich beschlossen, die Artikelserie unter Berücksichtigung einiger Kommentare neu zu starten . Nachdem ich meine Zielgruppe erkannt hatte, konnte ich den Fokus von meiner Art auf diejenigen verlagern, die ihn wirklich brauchen.

Antworten auf Kommentare zum vorherigen Artikel.


Bemerkung 1. Der Scheduler ist zu einfach.

Seit der Veröffentlichung des vorherigen Artikels hat sich der Code stark verändert. Es bildete sich ein vollwertiger Kern, der nicht mehr mikronuklear war. Es gibt Unterstützung für die anfängliche RAM-Disk (Kernel-Dateisystem) und den virtuellen Speicher (MMU). Es ist dem Kernel möglich geworden, benutzerdefinierte Programme zu schreiben. Es gab Systemaufrufe und die Clib-Bibliothek (stdio, string). Die Shell /initrd/sh.elf ist also ein separates Programm, das vom Elf-Bootloader analysiert und als Prozess ausgeführt wird.

Liste der Shell-Befehle: exec <file.elf>, ps, kill, exit. In diesem Fall kann die Shell von der Shell selbst aus gestartet werden (Demonstration von Multitasking).

Hinweis 2. Zu viel Magie hinter den Kulissen in den Video-Tutorials.

Ich habe beschlossen, den Text hervorzuheben, den ich gerade erkläre. Er ging auch zu Anfängern, die Klarheit und die einfachsten Dinge brauchen. Ehrlich gesagt war ich überrascht, dass Neulinge, die keine Erfahrung im Programmieren haben, sich für ein so komplexes Thema interessieren, obwohl es eine Sünde ist, sich zu verstecken, habe ich von dort aus begonnen. Ich habe die Tendenz von der Erklärung meines Betriebssystems zur Erklärung des Schreibens Ihres OK verschoben.

Bemerkung 3. Wo ist der Link zu Github ?

Jetzt ist sie es. In der Beschreibung des Videos auf YouTube (ja, ich möchte, dass Sie nicht an meinen Video-Tutorials vorbeikommen, schauen Sie sich zumindest ein Auge an).

Bemerkung 4. Wir sollten zuerst mit der Montage beginnen.

Das werden wir tun.

Bemerkung 5. Sie schreiben nichts anderes als nur einen Kommentar.

Ja, es war ein Fehler, sofort über etwas Großes zu sprechen. Jetzt gehen wir Schritt für Schritt voran und beginnen mit dem einfachsten Hello World-Kernel. Mit Videokursen können Sie ein ganzheitliches Bild der Welt erstellen, und der Quellcode auf dem Github wird Sie in die Details eintauchen lassen.

Inhaltsverzeichnis.


1. System bauen (make, gcc, gas). Erster Start (Multiboot). Starten Sie (qemu). C-Bibliothek (strcpy, memcpy, strext).
2. C-Bibliothek (sprintf, strcpy, strcmp, strtok, va_list ...). Erstellen der Bibliothek im Kernelmodus und im Benutzeranwendungsmodus.
3. Das Kernel-Systemprotokoll. Videospeicher Ausgabe an das Terminal (kprintf, kpanic, kassert).
4. Dynamischer Speicher, ein Haufen (kmalloc, kfree).
6. Organisation der Speicher- und Interrupt-Behandlung (GDT, IDT, PIC, Syscall). Ausnahmen
5. Virtueller Speicher (Seitenverzeichnis und Seitentabelle).
6. Der Prozess. Planer Multitasking. Systemaufrufe (kill, exit, ps).
7. Das Dateisystem des Kernels (initrd), elf und seiner Interna. Systemaufrufe (exec).
8. Zeichengerätetreiber. Systemaufrufe (ioctl, fopen, fread, fwrite). C-Bibliothek (fopen, fclose, fprintf, fscanf).
9. Die Shell als vollständiges Programm für den Kernel.
10. Benutzerschutzmodus (Ring3). Aufgabenstatussegment (tss).

Lass uns gehen. Teil 1. System erstellen und starten


In dem Artikel werde ich nur die wichtigsten Schritte auflisten . Eine ausführliche Erklärung finden Sie im Video-Tutorial zu diesem Artikel.

Du brauchst Linux. Wir werden gute alte Marken sammeln. Zum Kompilieren der ausführbaren Kerneldatei werden die folgenden Flags benötigt:

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 

Installieren Sie als Hardware-Emulator den qemu-Emulator unter Linux. Wir werden unseren Kernel so ausführen:

 qemu-system-i386 -kernel ./bin/kernel.elf 

Es wird auch ein kleines Skript für den Linker benötigt. Es wird benötigt, um Abschnitte an der richtigen Adresse und in der richtigen Reihenfolge zu laden. Auch darin werden wir den Einstiegspunkt angeben:

 OUTPUT_FORMAT(elf32-i386) ENTRY(start) SECTIONS { . = 0x100000; .text : { *(.text) } .data : { *(.data) } .bss : { *(.bss) } } 

Da der Kernel gemäß der Multiboot-Spezifikation geladen wird, wird der Header am Anfang des Codeabschnitts benötigt:

 .code32 .text # multiboot spec .align 4 multiboot: .long 0x1BADB002 # magic .long 0x00 # flags .long -(0x1BADB002 + 0x00) # checksum. m+f+c should be zero 

Es wird empfohlen, sofort zu Ihrem eigenen Stapel zu wechseln und eine globale Deskriptortabelle einzurichten. Definieren Sie unseren eigenen Stapel:

 .bss .fill 8192,1 # 8Kb stack: 

Schreiben Sie einen Einstiegspunkt. Möglicherweise ist die Syntax des Gnu-Assemblers ungewöhnlich. Ich habe einmal auch die Intel-Syntax bevorzugt, nachdem ich sie probiert und mich mit dem Linux-Quellcode befasst hatte, habe ich die AT & T-Syntax für mich selbst vollständig bevorzugt. Das Wichtigste ist, dass sie die entgegengesetzten Operanden haben. Der Rest wird intuitiv sein.

 start: cli movl $stack,%esp push %esp push %ebx /* address of struct multiboot_t */ call kernel_start /* should never return */ hlt 

Dies vervollständigt den Boilerplate-Code. Der Spaß beginnt. Jetzt können wir den Code in C schreiben. Zunächst definieren wir die Begrüßungsnachricht.

 char *hello = "Hello world!"; int screen_size = 80 * 25; 

Als nächstes schreiben wir den Einstiegspunkt selbst, an den der Assembler-Code die Kontrolle überträgt:

 /* * 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); } 

Hier zeigen wir einfach die Meldung auf dem Bildschirm an. Grundsätzlich können Sie den Code der ersten Lektion vollständig kopieren, da es sich um eine Vorlage handelt, die niemals geändert wird. Um etwas auf dem Bildschirm anzuzeigen, müssen Sie es nur direkt in den Videospeicher schreiben und jedes Zeichen mit einem Attributsymbol ergänzen. Dazu benötigen Sie eine eigene C-Bibliothek, die wir selbst für unsere Bedürfnisse schreiben. So ist es einfacher, den Prozess zu steuern. So stehen uns heute beispielsweise zwei bekannte Funktionen (strcpy, memcpy) und eine eigene Strext zur Verfügung, um das Attributbyte nach jedem Zeichen einzufügen.

Fazit


Das ist alles für heute. Sehen Sie sich das Video-Tutorial an und versuchen Sie, dasselbe selbst zu tun. Wenn es nicht funktioniert, können Sie in die Quellen für die Lektion auf dem Github schauen. Link zu Github in der Beschreibung des Video-Tutorials:

Literatur



1. James Molloy. Rollen Sie Ihr eigenes UNIX-Klon-Betriebssystem.
2. Zähne. Assembler für DOS, Windows, Unix
3. Kalaschnikow. Assembler ist einfach!
4. Tanenbaum. Betriebssysteme. Implementierung und Entwicklung.
5. Robert Love. Linux-Kernel Beschreibung des Entwicklungsprozesses.

Source: https://habr.com/ru/post/de466365/


All Articles