So erstellen Sie selbst ein Betriebssystem. So schreiben Sie ein Betriebssystem von Grund auf. Funktion – Tastatur-Interrupt-Handler

Was Sie wissen müssen, um ein Betriebssystem zu schreiben

Das Erstellen eines Betriebssystems gehört zu den schwierigsten Aufgaben beim Programmieren, da es umfassende und komplexe Kenntnisse über die Funktionsweise eines Computers erfordert. Welche? Finden wir es weiter unten heraus.

Was ist Betriebssystem?

Ein Betriebssystem (OS) ist Software, die mit Computerhardware und ihren Ressourcen arbeitet und eine Brücke zwischen der Hardware und Software eines Computers darstellt.

Computer der ersten Generation hatten kein Betriebssystem. Programme auf den ersten Computern enthielten Code für den direkten Betrieb des Systems, die Kommunikation mit Peripheriegeräten und Berechnungen, für die dieses Programm geschrieben wurde. Aufgrund dieser Situation war es selbst für Programme mit einfacher Logik schwierig, sie in Software zu implementieren.

Da Computer immer vielfältiger und komplexer wurden, wurde das Schreiben von Programmen, die sowohl als Betriebssystem als auch als Anwendung fungierten, einfach unpraktisch. Um das Schreiben von Programmen zu erleichtern, begannen Computerbesitzer daher, Software zu entwickeln. So entstanden Betriebssysteme.

Das Betriebssystem stellt alles bereit, was für die Ausführung von Benutzerprogrammen erforderlich ist. Ihr Erscheinen bedeutete, dass Programme nicht mehr die gesamte Arbeitsmenge auf dem Computer kontrollieren mussten (dies ist ein hervorragendes Beispiel für Kapselung). Jetzt mussten Programme speziell mit dem Betriebssystem zusammenarbeiten, und das System selbst kümmerte sich um Ressourcen und die Arbeit mit Peripheriegeräten (Tastatur, Drucker).

Kurze Geschichte der Betriebssysteme

C Sprache

Wie oben erwähnt, gibt es mehrere höhere Programmiersprachen zum Schreiben eines Betriebssystems. Am beliebtesten ist jedoch C.

Sie können hier mit dem Erlernen dieser Sprache beginnen. Diese Ressource führt Sie in grundlegende Konzepte ein und bereitet Sie auf fortgeschrittenere Aufgaben vor.

„Learn C the Hard Way“ ist der Titel eines anderen Buches. Neben der üblichen Theorie enthält es viele praktische Lösungen. Dieses Tutorial deckt alle Aspekte der Sprache ab.

Oder Sie wählen eines dieser Bücher:

  • „The C Programming Language“ von Kernighan und Ritchie;
  • „C Programming Absolute Beginner's Guide“ von Parry und Miller.

Betriebssystementwicklung

Nachdem Sie alles, was Sie über Informatik, Assemblersprache und C wissen müssen, beherrschen, sollten Sie mindestens ein oder zwei Bücher über die tatsächliche Betriebssystementwicklung lesen. Hier sind einige Ressourcen hierfür:

„Linux von Grund auf neu“. Hier wird der Prozess der Assemblierung des Linux-Betriebssystems besprochen (das Lehrbuch wurde in viele Sprachen übersetzt, darunter auch Russisch). Hier, wie auch in anderen Lehrbüchern, werden Ihnen alle notwendigen Grundkenntnisse vermittelt. Wenn Sie sich auf sie verlassen, können Sie versuchen, ein Betriebssystem zu erstellen. Um den Software-Teil des Betriebssystems professioneller zu gestalten, gibt es Ergänzungen zum Lehrbuch: „

Anleitung zum Erstellen eines Kernels für ein x86-System. Teil 1. Nur der Kern

Schreiben wir einen einfachen Kernel, der mit dem GRUB-Bootloader auf einem x86-System gebootet werden kann. Dieser Kernel zeigt eine Meldung auf dem Bildschirm an und wartet.

Wie bootet ein x86-System?

Bevor wir mit dem Schreiben des Kernels beginnen, wollen wir verstehen, wie das System startet und die Kontrolle an den Kernel überträgt.

Die meisten Prozessorregister enthalten beim Start bereits bestimmte Werte. Das auf die Adresse von Anweisungen zeigende Register (Instruction Pointer, EIP) speichert die Speicheradresse, an der sich die vom Prozessor ausgeführte Anweisung befindet. Die Standard-EIP ist 0xFFFFFFFF0. Somit beginnen x86-Prozessoren auf Hardwareebene ab der Adresse 0xFFFFFFF0 zu arbeiten. Dies sind tatsächlich die letzten 16 Bytes des 32-Bit-Adressraums. Diese Adresse wird als Reset-Vektor bezeichnet.

Jetzt stellt die Chipsatz-Speicherzuordnung sicher, dass 0xFFFFFFF0 zu einem bestimmten Teil des BIOS gehört, nicht zum RAM. Zu diesem Zeitpunkt kopiert sich das BIOS für einen schnelleren Zugriff in den RAM. Die Adresse 0xFFFFFFF0 enthält nur eine Anweisung, zu der Adresse im Speicher zu springen, an der eine Kopie des BIOS gespeichert ist.

Auf diese Weise beginnt die Ausführung des BIOS-Codes. Das BIOS sucht zunächst in einer voreingestellten Reihenfolge nach einem Gerät, von dem gestartet werden kann. Um festzustellen, ob das Gerät bootfähig ist, wird eine magische Zahl gesucht (das 511. und 512. Byte des ersten Sektors müssen gleich sein). 0xAA55).

Wenn das BIOS ein Startgerät findet, kopiert es den Inhalt des ersten Sektors des Geräts in den RAM, beginnend bei der physischen Adresse 0x7c00; geht dann zur Adresse und führt den heruntergeladenen Code aus. Dieser Code heißt Bootloader.

Der Bootloader lädt den Kernel an einer physischen Adresse 0x100000. Diese Adresse wird in allen großen Kerneln auf x86-Systemen als Startadresse verwendet.

Alle x86-Prozessoren starten in einem einfachen 16-Bit-Modus namens Real-Modus. Der GRUB-Bootloader schaltet den Modus auf 32-Bit um Sicherheitsmodus, Setzen des Low-Bits des Registers CR0 auf 1 . Somit wird der Kernel im 32-Bit-geschützten Modus geladen.

Beachten Sie, dass GRUB im Fall des Linux-Kernels die Linux-Boot-Protokolle erkennt und den Kernel im Real-Modus startet. Der Kernel wechselt automatisch in den geschützten Modus.

Was brauchen wir?

  • x86-Computer;
  • Linux;
  • ld (GNU-Linker);

Festlegen des Einstiegspunkts im Assembler

Egal wie sehr Sie sich am liebsten nur auf C beschränken würden, Sie müssen etwas in Assembler schreiben. Wir werden eine kleine Datei darauf schreiben, die als Ausgangspunkt für unseren Kernel dient. Es ruft lediglich eine in C geschriebene externe Funktion auf und stoppt den Programmfluss.

Wie können wir sicherstellen, dass dieser Code der Ausgangspunkt ist?

Wir werden ein Linker-Skript verwenden, das Objektdateien verknüpft, um die endgültige ausführbare Datei zu erstellen. In diesem Skript geben wir explizit an, dass wir Daten an der Adresse 0x100000 laden möchten.

Hier ist der Assembler-Code:

;;kernel.asm Bits 32 ;nasm-Direktive - 32-Bit-Abschnitt .text global start extern kmain ;kmain ist in der C-Datei definiert start: cli ;Block Interrupts mov esp, stack_space ;Stack-Zeiger setzen Aufruf kmain hlt ;den CPU-Abschnitt anhalten .bss resb 8192 ;8KB für Stack stack_space:

Die erste Anweisung, Bits 32, ist keine x86-Assembleranweisung. Dies ist eine Anweisung an den NASM-Assembler, die die Codegenerierung für einen Prozessor angibt, der im 32-Bit-Modus arbeitet. In unserem Fall ist dies nicht notwendig, aber grundsätzlich sinnvoll.

Der Abschnitt mit dem Code beginnt in der zweiten Zeile.

global ist eine weitere NASM-Direktive, die Quellcodesymbole global macht. Auf diese Weise weiß der Linker, wo sich das Startsymbol befindet – unser Einstiegspunkt.

kmain ist eine Funktion, die in der Datei kernel.c definiert wird. extern bedeutet, dass die Funktion woanders deklariert ist.

Dann kommt die Startfunktion, die die kmain-Funktion aufruft und den Prozessor mit der hlt-Anweisung stoppt. Aus diesem Grund deaktivieren wir Interrupts im Voraus mit der cli-Anweisung.

Im Idealfall müssen wir etwas Speicher zuweisen und mit einem Stapelzeiger (esp) darauf zeigen. Es sieht jedoch so aus, als hätte GRUB dies bereits für uns erledigt. Sie werden jedoch dennoch etwas Platz im BSS-Abschnitt zuweisen und den Stapelzeiger an seinen Anfang verschieben. Wir verwenden die resb-Anweisung, die die angegebene Anzahl von Bytes reserviert. Unmittelbar vor dem Aufruf von kmain wird der Stapelzeiger (esp) mit der mov-Anweisung auf die richtige Position gesetzt.

Kernel in C

In kernel.asm haben wir die Funktion kmain() aufgerufen. Daher sollte unser „C“-Code die Ausführung mit kmain() beginnen:

/* * kernel.c */ void kmain(void) ( const char *str = "mein erster Kernel"; char *vidptr = (char*)0xb8000; //video mem beginnt hier. unsigned int i = 0; unsigned int j = 0; /* diese Schleife löscht den Bildschirm * es gibt 25 Zeilen mit jeweils 80 Spalten; jedes Element benötigt 2 Bytes */ while(j< 80 * 25 * 2) { /* blank character */ vidptr[j] = " "; /* attribute-byte - light grey on black screen */ vidptr = 0x07; j = j + 2; } j = 0; /* this loop writes the string to video memory */ while(str[j] != "\0") { /* the character"s ascii */ vidptr[i] = str[j]; /* attribute-byte: give character black bg and light grey fg */ vidptr = 0x07; ++j; i = i + 2; } return; }

Unser Kernel löscht lediglich den Bildschirm und zeigt die Zeile „mein erster Kernel“ an.

Zuerst erstellen wir einen vidptr-Zeiger, der auf die Adresse zeigt 0xb8000. Im geschützten Modus beginnt der „Videospeicher“ ab dieser Adresse. Um Text auf dem Bildschirm anzuzeigen, reservieren wir 25 Zeilen mit 80 ASCII-Zeichen, beginnend bei 0xb8000.

Jedes Zeichen wird nicht mit den üblichen 8 Bits angezeigt, sondern mit 16. Das erste Byte speichert das Zeichen selbst und das zweite - Attributbyte. Es beschreibt die Formatierung des Zeichens, beispielsweise seine Farbe.

Um das grüne Zeichen s auf schwarzem Hintergrund darzustellen, schreiben wir dieses Zeichen in das erste Byte und den Wert 0x02 in das zweite. 0 bedeutet schwarzer Hintergrund, 2 bedeutet grüne Textfarbe.

Hier ist die Farbkarte:

0 – Schwarz, 1 – Blau, 2 – Grün, 3 – Cyan, 4 – Rot, 5 – Magenta, 6 – Braun, 7 – Hellgrau, 8 – Dunkelgrau, 9 – Hellblau, 10/a – Hellgrün, 11/b – Hellcyan, 12/c – Hellrot, 13/d – Hellmagenta, 14/e – Hellbraun, 15/f – Weiß.

In unserem Kernel verwenden wir hellgrauen Text auf schwarzem Hintergrund, sodass unser Attributbyte den Wert 0x07 hat.

In der ersten Schleife druckt das Programm ein leeres Symbol über die gesamte 80x25-Zone. Dadurch wird der Bildschirm gelöscht. Im nächsten Zyklus werden Zeichen aus der nullterminierten Zeichenfolge „mein erster Kernel“ mit einem Attributbyte gleich 0x07 in den „Videospeicher“ geschrieben. Dadurch wird die Zeichenfolge auf dem Bildschirm ausgegeben.

Verbindungsteil

Wir müssen kernel.asm mithilfe von NASM zu einer Objektdatei zusammenfügen. Verwenden Sie dann GCC, um kernel.c in eine andere Objektdatei zu kompilieren. Anschließend müssen sie an den ausführbaren Boot-Kernel angehängt werden.

Dazu verwenden wir ein Bindungsskript, das als Argument an ld übergeben wird.

/* * link.ld */ OUTPUT_FORMAT(elf32-i386) ENTRY(start) SECTIONS ( . = 0x100000; .text: ( *(.text) ) .data: ( *(.data) ) .bss: ( *( .bss) ) )

Zuerst werden wir fragen Ausgabeformat als 32-Bit Executable and Linkable Format (ELF). ELF ist ein Standard-Binärdateiformat für Unix x86-Systeme. EINTRAG akzeptiert ein Argument, das den Namen des Symbols angibt, das den Einstiegspunkt darstellt. ABSCHNITTE- das ist der wichtigste Teil. Es definiert das Markup unserer ausführbaren Datei. Wir legen fest, wie die verschiedenen Abschnitte verbunden werden sollen und wo sie platziert werden.

In Klammern nach SECTIONS zeigt der Punkt (.) den Positionszähler an, der standardmäßig 0x0 ist. Es kann geändert werden, und genau das tun wir.

Schauen wir uns die folgende Zeile an: .text: ( *(.text) ) . Das Sternchen (*) ist ein Sonderzeichen, das jedem Dateinamen entspricht. Der Ausdruck *(.text) bezeichnet alle .text-Abschnitte aus allen Eingabedateien.

Somit fügt der Linker alle Codeabschnitte der Objektdateien zu einem Abschnitt der ausführbaren Datei an der Adresse im Positionszähler (0x100000) zusammen. Danach entspricht der Zählerwert 0x100000 + der Größe des resultierenden Abschnitts.

Das Gleiche passiert mit anderen Abschnitten.

Grub und Multiboot

Jetzt sind alle Dateien bereit, um den Kernel zu erstellen. Aber es bleibt noch ein weiterer Schritt.

Es gibt einen Standard zum Laden von x86-Kernen mithilfe eines Bootloaders namens Multiboot-Spezifikation. GRUB startet unseren Kernel nur, wenn er diese Spezifikationen erfüllt.

Anschließend sollte der Kernel in seinen ersten 8 Kilobyte einen Header enthalten. Darüber hinaus muss dieser Header drei Felder enthalten, die jeweils 4 Byte groß sind:

  • magisch Feld: enthält magische Zahl 0x1BADB002 um den Kern zu identifizieren.
  • Feld Flaggen: Wir brauchen es nicht, setzen wir es auf Null.
  • Feld Prüfsumme: Wenn Sie es mit den beiden vorherigen addieren, sollten Sie Null erhalten.

Unser kernel.asm wird so aussehen:

;;kernel.asm ;nasm-Direktive – 32-Bit-Bits 32 Abschnitt .text ;multiboot spec align 4 dd 0x1BADB002 ;magic dd 0x00 ;flags dd – (0x1BADB002 + 0x00) ;Prüfsumme. m+f+c sollte Null sein global start extern kmain ;kmain ist in der C-Datei definiert start: cli ;Blockinterrupts mov esp, stack_space ;Stapelzeiger setzen Aufruf kmain hlt ;den CPU-Abschnitt anhalten .bss resb 8192 ;8KB für Stapel stack_space:

Den Kern aufbauen

Jetzt erstellen wir Objektdateien aus kernel.asm und kernel.c und verknüpfen sie mithilfe unseres Skripts.

Nasm -f elf32 kernel.asm -o kasm.o

Diese Zeile führt den Assembler aus, um die Objektdatei kasm.o im ELF-32-Format zu erstellen.

Gcc -m32 -c kernel.c -o kc.o

Die Option „-c“ stellt sicher, dass nach der Kompilierung keine versteckten Verknüpfungen auftreten.

Ld -m elf_i386 -T link.ld -o kernel kasm.o kc.o

Dadurch wird der Linker mit unserem Skript ausgeführt und eine ausführbare Datei namens erstellt Kernel.

Grub einrichten und Kernel starten

GRUB benötigt den Kernelnamen, um das Muster Kernel zu erfüllen. . Benennen Sie also den Kernel um. Ich habe meinen Kernel-701 genannt.

Legen Sie es nun im Verzeichnis ab /Stiefel. Dazu benötigen Sie Superuser-Rechte.

Fügen Sie in der GRUB-Konfigurationsdatei grub.cfg Folgendes hinzu:

Titel myKernel root (hd0,0) kernel /boot/kernel-701 ro

Vergessen Sie nicht, die Hiddenmenu-Direktive zu entfernen, falls vorhanden.

Starten Sie Ihren Computer neu und Sie sehen eine Liste der Kernel, einschließlich Ihres. Wählen Sie es aus und Sie werden Folgendes sehen:

Das ist dein Kern! Fügen wir ein Eingabe-/Ausgabesystem hinzu.

P.S.

  • Für alle Kernel-Tricks ist es besser, eine virtuelle Maschine zu verwenden.
  • Um den Kernel auszuführen grub2 Die Konfiguration sollte so aussehen: menuentry „kernel 7001“ ( set root="hd0,msdos1" multiboot /boot/kernel-7001 ro )
  • Wenn Sie den qemu-Emulator verwenden möchten, verwenden Sie: qemu-system-i386 -kernel kernel

Die Abkürzung „NT“ steht im Marketing für „Neue Technologien“, in der Projektdokumentation bedeutete sie jedoch etwas ganz anderes. Tatsache ist, dass Windows NT für den neuen Intel i860-Prozessor entwickelt wurde, der 1988 noch nicht veröffentlicht wurde. Sein Codename war „N10“ ( N T en).

Die erste Version, Windows NT 3.1, wurde fünf Jahre später, im Jahr 1993, veröffentlicht. Zu diesem Zeitpunkt zählte das Team bereits 250 Entwickler.

Windows heute

  • 1 Milliarde Nutzer
  • 140 Millionen Codezeilen (einschließlich Testcode und Instrumentierung)
    Windows-Code ist sehr unterschiedlich. Einige Teile wurden vor 20 Jahren geschrieben, andere erschienen erst in der aktuellen Version. Beispielsweise existiert der Web Services on Devices (WSD)-Code in Windows Vista in seiner ersten Version, der GDI-Code befindet sich in der Endphase seiner Entwicklung und bleibt nahezu unverändert, der DirectX-Code ist bereits gut entwickelt, verändert sich aber aktiv die Gegenwart.
  • 8000 Entwickler
  • 36 Lokalisierungssprachen
  • 20 Jahre Entwicklung

Windows-Entwicklung

Vor 20 bis 30 Jahren wurde nur eine Programmiermethode verwendet: „Wasserfall“. Es ist eine Folge:

Spezifikationen → Design → Implementierung → Testen → Lieferung.

Diese Methode funktioniert jedoch nur für kleine Projekte. Für ein Produkt wie Windows sind heute unterschiedliche Methoden erforderlich:

  • Produktzyklusmodell
  • Team-Software-Prozess
  • "Extremes Programmieren"

Alle diese Methoden haben sowohl Vor- als auch Nachteile. Abhängig von der Größe des Teams und dem Entwicklungsstadium der Komponente verwenden verschiedene Windows-Entwicklungsteams unterschiedliche Entwicklungsmethoden.
Für Windows als Gesamtprodukt wird das Produktzyklusmodell verwendet:

  • Zeiträume von 3-4 Monaten
  • Innerhalb der Periode - „Wasserfall“

Die größte Herausforderung bei der Entwicklung eines Produkts dieser Größenordnung besteht darin, dass die Entwicklung Zeit braucht. In der Anfangsphase werden die Probleme gelöst, die in der aktuellen Zeit und mit den verfügbaren Mitteln bestehen. Aber das Einzige, was beständig ist, ist, dass sich alles ändern wird. Im Laufe der Jahre der Entwicklung:

  • Anforderungen werden sich ändern
  • Die Möglichkeiten werden sich ändern
  • Der Arbeitsplan wird sich ändern
  • Das Projekt wird sich ändern
  • Die Benutzer werden sich ändern

Trotz der Tatsache, dass sich verschiedene Teams unterschiedlich entwickeln, gibt es „universelle“ Regeln:

  • Veröffentlichung von Zwischenversionen (Milestones, Beta, CTP) für die Masse der Tester
  • Freigabe interner Baugruppen mit kurzen Zyklen (1 Tag)
  • Einfachheit und Zuverlässigkeit des Designs
  • Persönliche und Team-Codeüberprüfungen
  • Unit-Tests
  • Build-Verifizierungstests
  • Jede Zwischenbaugruppe muss von hoher Qualität sein (was geschrieben steht, muss funktionieren)

Ich möchte persönlich anmerken, dass ich nach einem Monat Arbeit mit Windows 7 Build 6801 als Hauptbetriebssystem auf meinem Heimcomputer einen positiven Eindruck von diesem Build gewonnen habe.

Der gesamte Windows-Entwicklungsprozess basiert auf dem täglichen Build:

  • Das ist der Puls des Produkts
  • Die Entwicklung hört nie auf
  • Täglicher automatischer Test
  • Frühzeitige Integration
  • Verantwortung des Entwicklers
  • Offensichtlicher Zustand des Produkts

Es war einmal, dass es nur einen Quellcodezweig gab und alle Entwickler Änderungen direkt daran vornahmen. Jetzt ist das Entwicklungsteam so groß, dass es nicht funktioniert. Viele Zweige werden unterstützt, darunter der Hauptzweig – WinMain. Jedes Labor verfügt über einen eigenen lokalen Entwicklungszweig, in den Änderungen integriert werden. Getestete Änderungen werden schließlich in WinMain integriert.

Täglicher Entwicklungszyklus:

  • 15:00 – Änderungen zur Integration in das Quellcode-Verwaltungssystem freigegeben
  • Build 6 Versionen (kostenlos/geprüft – x86, x64, IA64)
  • 18:00 – Neue Versionen stehen zum Testen zur Verfügung
  • Die neue Version wird zum Testen auf mehreren tausend Workstations und Servern installiert
  • Automatisierter Stresstest
  • 05:00 – Prüfberichte werden analysiert, Fehler diagnostiziert
  • 09:00 – Zusammenfassende Berichte werden automatisch an die Teams gesendet
  • 09:30 – Konsolidiertes Treffen der Teamleiter zur Festlegung von Zielen

Alle Projektteilnehmer, einschließlich der höchsten Führungskräfte, verwenden Zwischenversionen auf ihren Arbeitscomputern (und normalerweise zu Hause).

In was ist Windows geschrieben?

  • C, C++, C#, Assembly (x86, x64, IA64)
    Assembler werden in eher begrenztem Umfang in Situationen eingesetzt, in denen sie nicht vermieden werden können.
  • Visual Studio, Source Insight, Build, nmake
  • Source Depot – Quellcodeverwaltungssystem
  • WinDbg, KD, NTSD – Debugger

Viele interne Tools, wie z. B. Build, können von microsoft.com/whdc/devtools heruntergeladen werden.

Änderungen am Kernel von Windows 7

Der Windows 7-Kernel hat folgende Änderungen erfahren:

  • Refactoring
    Warum kann ich das Grafiksubsystem in Windows nicht entfernen?
    Die Antwort auf diese Frage aus technischer Sicht lautet, dass das Grafiksubsystem in Windows nicht unabhängig ist, sondern Teil des Win32-Subsystems.
    Windows 7 hat viele Low-Level-Komponenten umgestaltet, um Abhängigkeiten aufzulösen. Dies wird für Benutzer nicht sichtbar sein, es werden nur neue DLLs angezeigt, beispielsweise wurde kernel32.dll in kernel32.dll und kernelbase.dll aufgeteilt.
    Diese Partitionierung ermöglichte die Zuweisung eines minimalen Kernels namens MinWin (20 Megabyte auf der Festplatte).
  • EFI-Unterstützung für x86 und x64 (wie Vista SP1)
    Viele Hersteller versuchen, das BIOS zugunsten von EFI abzuschaffen.
  • Booten von VHD (Virtuelle Festplatte)
  • Parallele Initialisierung von Geräten und Start von Diensten
    Beim Booten von Windows dauert der Aufbau des Gerätebaums ziemlich lange. Der PNP-Manager muss Bustreiber (PCI, USB, FireWire usw.) abfragen, um zu sehen, welche Geräte sie haben. Und die meiste Zeit wartet der Prozessor darauf, dass Geräte reagieren (oder auch nicht). Denn um Geräte am Bus zu identifizieren, müssen Sie diese abfragen. Wenn dies der Fall ist, antworten sie. Wenn nicht, müssen Sie warten und der Prozessor ist im Leerlauf. Durch die parallele Ausführung dieser Aufgaben werden die Ladezeiten verkürzt.
  • Entfernen der Dispatcher-Sperre vom Scheduler und der PFN-Sperre vom Speichermanager
    In den letzten Jahren sind die Prozessortaktfrequenzen nicht gestiegen, und die Entwicklung geht in Richtung einer Erhöhung der Anzahl parallel ausgeführter Befehle sowohl auf Einzelkernebene als auch auf Systemebene (Multicore). In dieser Hinsicht wurde viel Arbeit geleistet, um die Skalierung zu verbessern.
    Die beiden „heißesten“ Sperren im Kernel, die Dispatcher-Sperre und die PFN-Sperre, wurden entfernt.
    Die Dispatcher-Sperre wurde vom Scheduler verwendet, wenn sich der Status von Threads änderte. Diese Sperre wurde entfernt und der Thread-Status „Warten“ wurde in mehrere Bereiche aufgeteilt:
    • Warten: In Bearbeitung
    • Ausstehend: Abgeschlossen
    • Warten: Abgesagt
    Beim Ändern der Attribute physischer Speicherseiten wurde eine PFN-Sperre verwendet. In einem Multiprozessorsystem forderte jeder Prozessor den Zugriff auf diese Sperre an, was zu einem hohen Zeitaufwand führte.
  • Unterstützt 256 logische Prozessoren
    Zuvor wurde in Windows das Maschinenwort als Affinitätsmaske verwendet. Dies geschah, weil es einfach war, freie Prozessoren zu finden – jedes Bit repräsentiert einen Prozessor. Dementsprechend unterstützte ein 32-Bit-System 32 logische Prozessoren und ein 64-Bit-System 64.
    In Windows 7 wurde durch den Übergang zum Affinitätsmaskensegmentmodell die Unterstützung von 256 logischen Prozessoren möglich. Prozessoren wurden in Gruppen/Segmente gruppiert. Jede Gruppe kann bis zu 64 Prozessoren enthalten. Das Ergebnis ist Abwärtskompatibilität, alte Programme „sehen“ nur Prozessoren einer Gruppe und neue Programme, die neue Schnittstellen verwenden, funktionieren mit allen Prozessoren im System.
  • Verbesserte Energieeinsparung: Deaktivierung von ProzessorsockelHeutzutage stehen nicht nur Laptopbesitzer, sondern auch Besitzer von Rechenzentren vor einem ernsthaften Problem der Energieeinsparung. In den USA werden 2 % des Stroms von Computer-Rechenzentren verbraucht. Viele von ihnen schalten in Zeiten geringer Benutzeraktivität (Wochenenden) einen Teil ihrer Server ab.
    Es wurde festgestellt, dass es viel rentabler ist, den gesamten Prozessorsockel zu deaktivieren, als einen Kern auf mehreren, weil In diesem Fall können Sie die gesamte Socket-Unterstützungsinfrastruktur (Speichercontroller) deaktivieren.

Windows-Wartung, Updates

Bisher erfolgten Aktualisierungen oft kumulativ. Dies bedeutete, dass, wenn der fehlerhafte Code in einem frühen Update einer Komponente enthalten war, auch spätere Versionen diesen Code enthalten würden. Allerdings benötigen nicht alle Benutzer alle Updates, sie haben unterschiedliche Konfigurationen.

Es gibt jetzt 2 Versionen des Quellcodes nach der Veröffentlichung (RTM) unter Windows:

  • RTM GDR (General Distribution Release)
    Enthält die wenigen Änderungen, die für alle gedacht sind. Hauptsächlich Sicherheitsupdates.
  • RTM LDR (Limitierte Vertriebsversion)
    Bei der Installation eines Updates wählt der Windows Update-Client den benötigten Zweig aus und installiert den Code daraus.

Erstellen eines Sicherheitsupdates

Die Arbeit zur Erstellung eines Sicherheitsupdates beginnt mit der Identifizierung einer Schwachstelle. Es gibt eine Menge verschiedener Erkennungsmethoden – interne Sicherheitsteams, Sicherheitspartner, Entwickler. Wenn eine Schwachstelle erkannt wird, beginnen zwei parallele Prozesse:

  • Entwicklung eines Fixes für alle Plattformen
  • Suche nach „Optionen“
    Groß angelegte Suche nach ähnlichen Schwachstellen auf allen Plattformen. Suchen Sie nicht nach identischem Code, sondern nach ähnlichem.

Sobald ein Fix entwickelt ist, beginnen die Codeüberprüfungen. Wenn sie abgeschlossen sind, wird der Fix in den Build integriert und der Build wird zum Testen gesendet:

  • Manuelle und automatische Prüfung von Komponenten
  • Automatisches Testen von Dateiformatverzerrungen, Netzwerkkomponenten usw. (mehr als eine Million Optionen)
  • Testen des Systems als Ganzes, einschließlich Abwärtskompatibilitätstests

Nur Fixes, die alle Qualitätskriterien erfüllen, dürfen im Windows Update- und Download-Center veröffentlicht werden.

  • Weiterleiten >

Wenn wir zum Punkt kommen...

Ein Betriebssystem ist eine Sache, die (normalerweise) Multitasking implementiert und die Verteilung der Ressourcen zwischen diesen Aufgaben und im Allgemeinen verwaltet. Zumindest müssen Sie sicherstellen, dass sich Aufgaben nicht gegenseitig beeinträchtigen und in verschiedenen Bereichen des Speichers arbeiten und abwechselnd mit Geräten arbeiten. Sie müssen auch die Möglichkeit bereitstellen, Nachrichten von einer Aufgabe an eine andere zu übertragen.

Außerdem muss das Betriebssystem, sofern ein Langzeitspeicher vorhanden ist, Zugriff darauf gewähren, also alle Funktionen für die Arbeit mit dem Dateisystem bereitstellen. Es ist ein Minimum.

Fast überall muss der allererste Boot-Code in Assembler geschrieben werden – es gibt eine Reihe von Regeln darüber, wo er sein sollte, wie er aussehen sollte, was er tun sollte und welche Größe er nicht überschreiten sollte.

Für einen PC müssen Sie einen Bootloader auf ASMA schreiben, der vom BIOS aufgerufen wird und der, ohne vier und ein paar hundert Bytes zu überschreiten, etwas tun und das Hauptbetriebssystem starten sollte – die Kontrolle an den Hauptcode übertragen, der in Die nahe Zukunft kann in C geschrieben werden.

Für ARM müssen Sie eine Interrupt-Tabelle auf ACMA erstellen (Reset, verschiedene Fehler, IRQ-, FIQ-Interrupts usw.) und die Kontrolle an den Hauptcode übertragen. Allerdings ist in vielen Entwicklungsumgebungen solcher Code für fast jeden Controller verfügbar.

Das heißt, dafür benötigen Sie:

  1. Kennen Sie die Assemblersprache der Zielplattform.
  2. Kennen Sie die Prozessorarchitektur und alle Arten von Dienstbefehlen und Registern, um ihn für den Betrieb im gewünschten Modus zu konfigurieren. Bei einem PC ist dies beispielsweise ein Übergang in den geschützten Modus oder in den 64-Bit-Modus... Bei ARM ist dies die Einstellung der Taktung des Kerns und der Peripheriegeräte.
  3. Erfahren Sie genau, wie das Betriebssystem startet und wo und wie Sie Ihren Code pushen müssen.
  4. Kennen Sie die C-Sprache – ohne Erfahrung ist es schwierig, großen Code in Asma zu schreiben, und die Wartung wird noch schwieriger. Daher müssen Sie den Kernel in C schreiben.
  5. Kennen Sie die Funktionsprinzipien des Betriebssystems. Nun, es gibt viele Bücher auf Russisch zu diesem Thema, obwohl ich nicht weiß, ob sie alle gut sind.
  6. Haben Sie viel, viel Geduld und Ausdauer. Es wird Fehler geben, die gefunden und korrigiert werden müssen. Sie müssen auch viel lesen.
  7. Habe viel, viel Zeit.

Weiter. Nehmen wir an, Sie haben etwas geschrieben. Wir müssen dieses Ding testen. Entweder Sie benötigen ein physisches Gerät, auf dem die Experimente stattfinden (Debugboard, zweiter Computer), oder einen Emulator dafür. Die zweite Möglichkeit ist normalerweise einfacher und schneller zu verwenden. Für PC zum Beispiel VMWare.

Auch im Internet gibt es jede Menge Artikel zu diesem Thema, wenn man gut recherchiert. Es gibt auch viele Beispiele für vorgefertigte Betriebssysteme mit Quellcodes.

Wenn Sie wirklich möchten, können Sie sich sogar den Quellcode des alten Kernels von NT-Systemen (Windows) ansehen, sowohl separat (der von Microsoft veröffentlicht wurde, mit Kommentaren und verschiedenen Arten von Referenzmaterialien) als auch in Verbindung mit dem alten Betriebssystem (durchgesickert).

WikiHow funktioniert wie ein Wiki, was bedeutet, dass viele unserer Artikel von mehreren Autoren verfasst werden. Während der Erstellung dieses Artikels haben 90 Personen, darunter auch anonyme Personen, daran gearbeitet, ihn zu bearbeiten und zu verbessern.

Betriebssysteme, die aus Hunderttausenden Codezeilen bestehen, ermöglichen Benutzern die Interaktion mit Computerhardware. Sie werden üblicherweise in den Programmiersprachen C, C++ und Assembler geschrieben.

Schritte

    Lernen Sie zunächst das Programmieren. Assembler-Kenntnisse sind erforderlich; Es wird auch dringend empfohlen, Kenntnisse in anderen weiteren Programmiersprachen auf niedrigerem Niveau zu haben, wie z. B. C.

    Entscheiden Sie, auf welchem ​​Gerät Sie das Betriebssystem laden möchten. Dies kann eine CD, DVD, ein Flash-Speichergerät, eine Festplatte oder ein anderer Computer sein.

    Entscheiden Sie, wie Ihr Betriebssystem aussehen soll. Sollte es ein vollwertiges Betriebssystem mit grafischer Benutzeroberfläche (GUI) sein oder vielleicht etwas Minimalistischeres? Sie müssen wissen, in welche Richtung Sie gehen müssen, bevor Sie mit dem Prozess beginnen.

    Prüfen Sie, welche Prozessorplattform Ihr Betriebssystem unterstützt. AI-32 und x86_64 sind die beiden gängigsten Versionen für Personalcomputer und können daher als die beste Wahl angesehen werden.

    Entscheiden Sie, ob Sie lieber alles von Grund auf selbst machen möchten, oder ob es Kernel gibt, auf deren Basis Sie das System aufbauen möchten. Linux from Scratch ist ein Projekt für diejenigen, die beispielsweise ihre eigene Linux-Distribution erstellen möchten.

    Wählen Sie, ob Sie Ihren eigenen Bootloader oder den vorgefertigten Grand Unified Bootloader (GRUB) verwenden möchten. Da das Codieren Ihres eigenen Boot-Programms umfassende Kenntnisse der Computerhardware und des BIOS erfordert, kann es den Programmierplan für den Live-Kernel verschieben.

    Treffen Sie eine Entscheidung über die Programmiersprache, die Sie verwenden möchten. Natürlich ist es durchaus möglich, ein Betriebssystem in einer Sprache wie Pascal oder BASIC zu entwickeln, aber es ist besser, es in C oder Assembler zu schreiben. Die Assemblersprache ist unbedingt erforderlich, da einige wichtige Teile des Betriebssystems Kenntnisse dieser bestimmten Sprache erfordern. C++ hingegen enthält die Schlüsselwörter, die zum Ausführen der Vollversion des Betriebssystems erforderlich sind.

    • Um ein Betriebssystem mit C- oder C++-Code zu erstellen, verwenden Sie natürlich den einen oder anderen Compiler. Das bedeutet, dass Sie das Handbuch/die Anleitung/Dokumentation für den ausgewählten C/C++-Compiler lesen müssen, das im Lieferumfang der Software enthalten ist oder auf der Website des Händlers verfügbar ist. Sie müssen viele komplexe Dinge über den Compiler lernen, zusätzlich zu seinem Design und ABI, um C++ zu verbessern. Von Ihnen wird erwartet, dass Sie die verschiedenen Ausführungsaufgabenformate (ELF, PE, COFF, reguläre Binärdatei usw.) verstehen und beachten, dass das native Windows PE-Format (.exe) urheberrechtlich geschützt ist.
  1. Wählen Sie An(API). Eine Auswahl guter APIs ist POSIX, da es gut dokumentiert ist. Alle Unix-Systeme unterstützen POSIX zumindest teilweise, daher wäre es trivial, Unix-Programme auf Ihrem Betriebssystem zu bündeln.

    Entscheiden Sie sich für ein Design. Es gibt monolithische Kernel und Mikrokernel. Monolithische Kernel führen alle Dienste im Kernel aus, während Mikrokernel über einen kleinen Kernel verfügen, der mit einer benutzerdefinierten Implementierung von Diensten gekoppelt ist. Im Allgemeinen sind monolithische Kernel schneller, Mikrokernel verfügen jedoch über eine bessere Isolierung und einen besseren Schutz vor möglichen Fehlern.

    Berücksichtigen Sie Entwicklung und Teamarbeit. Auf diese Weise verbringen Sie weniger Zeit mit der Lösung großer Probleme und können so in kürzerer Zeit ein besseres Betriebssystem erstellen.

    Löschen Sie Ihre Festplatte nicht vollständig. Denken Sie daran, dass durch das Formatieren der Festplatte alle Ihre Daten dauerhaft gelöscht werden! Verwenden Sie GRUB oder einen anderen Manager, um Ihren Computer dupliziert von einem anderen Betriebssystem aus zu starten, bis Ihre Version voll funktionsfähig ist.

    Fangen Sie klein an. Achten Sie zunächst auf die kleinen Dinge wie Textanzeige und Unterbrechungen, bevor Sie sich komplexen Elementen wie Speicherverwaltung und Multitasking zuwenden.

    Bewahren Sie eine Sicherungskopie der neuesten Arbeitsversion auf. Dies bietet eine gewisse Sicherheit für den Fall, dass mit der aktuellen Version Ihres Betriebssystems oder späteren Ergänzungen etwas völlig schief geht. Wenn Ihr Computer ausfällt und nicht mehr booten kann, wie Sie selbst wissen, ist eine zweite Kopie zum Arbeiten eine hervorragende Gelegenheit, um die bestehenden Probleme zu beheben.

    Testen Sie Ihr neues Betriebssystem auf einer virtuellen Maschine. Anstatt Ihren Computer jedes Mal neu zu starten, wenn Sie Änderungen vornehmen oder Dateien von Ihrem Produktionscomputer auf die Testmaschine übertragen, können Sie eine Anwendung verwenden, um das Betriebssystem in einer virtuellen Maschine auszuführen, während Ihr aktuelles Betriebssystem weiterhin ausgeführt wird. Zu den VM-Anwendungen gehören VMWare (das auch über einen frei verfügbaren Server verfügt), alternative Open Source, Bochs, Microsoft Virtual PC (nicht kompatibel mit Linux) und XVM VirtualBox.

    Geben Sie eine Release-Version frei. Auf diese Weise können Benutzer Sie über mögliche Fehler in Ihrem Betriebssystem informieren.

  2. Das Betriebssystem sollte außerdem benutzerfreundlich sein. Fügen Sie daher unbedingt nützliche Funktionen hinzu, die ein integraler Bestandteil Ihres Designs werden.

    • Überlegen Sie nach Abschluss der Entwicklung, ob Sie den Code öffentlich verfügbar oder privat machen möchten.
    • Stellen Sie sicher, dass Sicherheitsfunktionen oberste Priorität haben, wenn Sie möchten, dass Ihr System funktionsfähig ist.
    • Starten Sie kein Betriebssystem-Entwicklungsprojekt mit dem Ziel, Programmieren zu lernen. Wenn Sie C, C++, Pascal oder eine der anderen relevanten Sprachen und Funktionen, einschließlich Zeigertypen, Bitoperationen auf niedriger Ebene, Bitumschaltung, Inline-Assembler usw., nicht kennen, sind Sie noch nicht bereit Betriebssystem erstellen.
    • Durchsuchen Sie Portale wie OSDev und OSDever, die Ihnen bei der Verbesserung Ihres eigenen Betriebssystems helfen. Bitte beachten Sie insbesondere, dass die OSDev.org-Community es bei den meisten Problemen vorzieht, dass Sie den Inhalt der Website selbst konsultieren, anstatt einem Forum beizutreten. Sollten Sie sich dennoch dazu entschließen, in die Reihen der Forumsmitglieder aufgenommen zu werden, müssen dafür bestimmte Voraussetzungen gegeben sein. Sie müssen über umfassende Kenntnisse in C oder C++ und der x86-Assemblersprache verfügen. Sie sollten auch allgemeine und komplexe Konzepte in der Programmierung wie verknüpfte Listen, Warteschlangen usw. verstehen. Die OSDev-Community legt in ihren Regeln ausdrücklich fest, dass niemand neue Programmierer betreuen wird. Wenn Sie versuchen, ein Betriebssystem zu entwickeln, ist es selbstverständlich, dass Sie ein Programmierer sind. Sie müssen außerdem das Prozessorhandbuch für die von Ihnen ausgewählte Prozessorarchitektur lesen; zum Beispiel x86 (Intel), ARM, MIPS, PPC usw. Ein solches Nachschlagewerk zum Prozessoraufbau lässt sich leicht über eine Google-Suche („Intel Manuals“, „ARM Manuals“ etc.) finden. Treten Sie nicht dem OSDev.org-Forum bei, um offensichtliche Fragen zu stellen. Dies führt einfach zu Antworten wie „Lesen Sie das verdammte Handbuch.“ Zunächst sollten Sie versuchen, Wikipedia und Handbücher für die verschiedenen Tools zu lesen, die Sie verwenden möchten.
    • Suchen Sie nach möglichen Funklöchern und anderen Fehlern. Lücken, Sackgassen und andere Probleme können sich auf das Design Ihres Betriebssystems auswirken.
    • Wenn Sie eine einfachere Methode wünschen, denken Sie an Linux-Distributionen wie Fedora Revisor, Custom Nimble X, Puppy Remaster, PCLinuxOS mklivecd oder SUSE Studio und SUSE KIWI. Das erstellte Betriebssystem gehört jedoch dem Unternehmen, das diesen Dienst erstmals eingeführt hat (obwohl Sie unter der GPL das Recht haben, ihn frei zu verteilen, zu ändern und nach Belieben auszuführen).
    • Eine gute Lösung wäre, eine völlig neue Partition für das zu entwickelnde Betriebssystem zu erstellen.

    Warnungen

    • Durch unvorsichtiges Kopieren des Betriebssystems auf die Festplatte kann diese vollständig beschädigt werden. seid vorsichtig
    • Sie werden nicht in zwei Wochen ein komplett fertiges System haben. Beginnen Sie mit einem bootfähigen Betriebssystem und gehen Sie dann zu interessanteren Dingen über.
    • Wenn Sie etwas Rücksichtsloses tun, wie zum Beispiel zufällige Bytes auf zufällige I/O-Ports schreiben, zerstören Sie Ihr Betriebssystem und könnten (theoretisch) Ihre Hardware kaputt machen.
    • Erwarten Sie nicht, dass es einfach ist, ein hochwertiges Betriebssystem zu erstellen. Es gibt viele komplexe Zusammenhänge. Damit das Betriebssystem beispielsweise mehrere Prozessoren verarbeiten kann, muss Ihr Speichermanager über „Sperrmechanismen“ verfügen, um zu verhindern, dass zusätzliche Prozessoren gleichzeitig auf dieselbe Ressource zugreifen. Bei den verwendeten „Blöcken“ handelt es sich um einen Planer, der sicherstellt, dass jeweils nur ein Prozessor auf eine kritische Ressource zugreift, während alle anderen im Leerlauf sind. Die Funktion des Schedulers hängt jedoch von der Anwesenheit des Speichermanagers ab. Dies ist ein Beispiel für eine Deadlock-Abhängigkeit. Es gibt keine Standardmethode zur Lösung solcher Probleme. Von jedem Betriebssystementwickler wird erwartet, dass er über die nötigen Fähigkeiten verfügt, um eine eigene Lösung zu entwickeln.
Fortsetzung des Themas:
Apfel

Betreiber / 24.10.2017 MTS-Telefon-Firmware (Smart Race, Sprint, Surf, Run 4G) MTS bietet seinen Kunden wie jeder andere Betreiber verschiedene Smartphone-Modelle für...