Windows-9x-Subsystem für Linux
(social.hails.org)- Ein experimentelles Projekt, das einen modernen Linux-Kernel (6.19) kooperativ innerhalb des Windows-9x-Kernels ausführt und so die vollständigen Funktionen beider Betriebssysteme gleichzeitig nutzbar macht
- Anders als WSL wird keine Hardware-Virtualisierung verwendet, daher läuft es sogar auf einem 486er
- Paging, Speicherschutz und präemptives Scheduling sowie andere moderne OS-Funktionen werden in der Windows-9x-Umgebung verfügbar, und Anwendungen beider Systeme können ohne Neustart nebeneinander laufen
- Es besteht aus drei Komponenten: einem gepatchten Linux-Kernel, einem VxD-Treiber und dem wsl.com-Client; User-Mode Linux wurde dafür so umgebaut, dass es Win9x-Kernel-API-Aufrufe nutzt
- Systemaufrufe werden wegen der Begrenzung der kurzen Interrupt-Deskriptor-Tabelle von Win9x nicht über
int 0x80, sondern über einen General Protection Fault (GPF)-Handler verteilt - „Proudly written without AI“, Lizenz GPL-3
WSL9x - codeberg.org/hails/wsl9x
Überblick
- WSL9x ist ein Linux-Subsystem für Windows 9x, das einen modernen Linux-Kernel (zum Zeitpunkt der Beschreibung 6.19) kooperativ innerhalb des Windows-9x-Kernels ausführt
- Dadurch lassen sich die vollständigen Funktionen beider Betriebssysteme gleichzeitig nutzen, darunter Paging, Speicherschutz und präemptives Scheduling
- Anwendungen beider Betriebssysteme können ohne Neustart nebeneinander ausgeführt werden
- Es wurde direkt und ohne AI geschrieben
Technische Struktur
- WSL9x besteht aus drei Komponenten
- gepatchter Linux-Kernel (
win9x-um-6.19-Branch) - VxD-Treiber
- wsl.com-Clientprogramm
- gepatchter Linux-Kernel (
VxD-Treiber
- Zuständig für die Initialisierung von WSL9x; der Einstiegspunkt ist
vxd/wsl9x.asm - Richtet das anfängliche Mapping des Kernel-Codes ein und lädt
vmlinux.elfüber DOS-Interrupts von der Festplatte (vxd/loader.c,vxd/fs.asm) - Der Kernel wird mit der festen Basisadresse
0xd0000000kompiliert - Startet einen neuen Thread in der System-VM und reserviert einen 16-KiB-Stack für den Linux-Einstieg
- Wechselt anschließend in eine Ereignisschleife, die den Kernel-Einstieg, IRQ-Dispatch, die Rückkehr in den User-Space und Leerlaufzustände verarbeitet (
vxd/entry.c)
Systemaufrufe und Behandlung von Page Faults
- Der Treiber verarbeitet Page Faults und Systemaufrufe als User-Space-Ereignisse, die an den Kernel weitergeleitet werden müssen
- Systemaufrufe werden über einen General Protection Fault (GPF)-Handler verarbeitet
- Win9x hat keine ausreichend lange Interrupt-Deskriptor-Tabelle, um einen sauberen Handler für den Linux-i386-Systemaufruf-Interrupt
int 0x80zu installieren - Der GPF-Handler untersucht die fehlerauslösende Instruktion und schiebt, falls es sich um
int 0x80handelt, den Instruktionszeiger so weiter, als wäre der Interrupt erfolgreich gewesen, und dispatcht dann zum Linux-Systemaufruf (vxd/fault.c)
- Win9x hat keine ausreichend lange Interrupt-Deskriptor-Tabelle, um einen sauberen Handler für den Linux-i386-Systemaufruf-Interrupt
Umbauten am Linux-Kernel
- Basiert auf User-Mode Linux, wurde jedoch so modifiziert, dass statt der POSIX-API die Windows-9x-Kernel-API aufgerufen wird
- Läuft nicht im User-Modus (Ring 3), sondern in Ring 0 (Supervisor-/Kernel-Modus)
- Ein erheblicher Teil der Win9x-Kernel-Integration, einschließlich des Context Switching, befindet sich auf der Linux-Kernel-Seite
- Wichtiger Code liegt in
linux/arch/um/os-Win95 - Einstiegspunkt:
_startinmain.c; zentrale Dateien sindprocess.cundmmu.c
- Wichtiger Code liegt in
wsl.com-Client
- Ein 16-Bit-DOS-Programm, implementiert in
wsl/wsl.asm - Nutzt die MS-DOS-Eingabeaufforderung als TTY-Fenster, ohne eine separate TTY-Implementierung zu benötigen
- Beim Start ruft es die WSL9x-V86-API (
vxd/v86_api.asm) auf, um eine ungenutzte Konsole zuzuweisen, und meldet an, dass deren Ausgabe an das Programm dispatcht werden soll - Danach geht es in eine Ereignisschleife über, wartet auf IRQs und versucht bei Interrupts, Tastatureingaben zu lesen
- Dient außerdem als Synchronisationspunkt für den Konsolentreiber (
vxd/console.c)- Wenn Linux-Ausgabe bereitsteht, wird ein Ereignis geplant und im Kontext der MS-DOS-VM
int 0x29ausgeführt, um Zeichen im DOS-Fenster auszugeben - Dieser Interrupt ist auch der Punkt, an dem DOS-ANSI-Treiber wie NNANSI die Terminalausgabe abfangen, um ANSI-Escape-Codes umzusetzen
- Wenn Linux-Ausgabe bereitsteht, wird ein Ereignis geplant und im Kontext der MS-DOS-VM
Anforderungen für Build und Ausführung
- Erfordert eine Cross-Toolchain für das Ziel
i386-linux-musl(empfohlen wird musl-cross-make) - Erfordert die Open Watcom v2 Toolchain zum Bauen der Windows-Komponenten
- Erfordert den Build des gepatchten Linux-Kernels aus dem Branch
win9x-um-6.19 - Die Umgebungsvariablen
WATCOMundLINUXmüssen passend gesetzt werden (Beispiele siehe.envrc.example) - Benötigt ein Festplatten-Image
hdd.base.img, auf dem Windows 9x bereits vorinstalliert ist - Bei Ausführung von
makewird ein für WSL9x vorbereiteteshdd.imgerzeugt - Durch Ausführen von
wslin der MS-DOS-Eingabeaufforderung wird ein pty geöffnet; für ANSI-Farben wird empfohlen, vorher einen Treiber wiennansi.comzu laden
Lizenz
- GPL-3
2 Kommentare
Hacker-News-Kommentare
http://www.colinux.org/
https://github.com/wishstudio/flinux
flinux war strukturell eigentlich näher an WSL1, während CoLinux eher wie WSL2 wirkte, weil dort ein Linux-Kernel daneben mitlief.
Technisch wirkte Cygwin auf mich eher wie der orthodoxe Ansatz. Statt mit Gewalt externe Linux-Mechanik einzubauen, ließ es native POSIX-Binärdateien auf Windows laufen, und mir gefiel auch, dass es mit einer leichten DLL-Verknüpfung auskam, ohne Ring 0 anzufassen.
Allerdings fehlte damals der Komfort eines CLI-Paketmanagers, und wenn ich tatsächlich unter Windows gearbeitet habe, war ich ziemlich stark bei CoLinux.
Das Hauptproblem, an das ich mich erinnere, war die DLL-Hölle. Wenn zum Beispiel ein OpenSSH-Port für Windows seine eigene
cygwin1.dllmitbrachte, kam es oft zu Versionskonflikten.Trotzdem war der geringe Overhead in einer Zeit mit wenig RAM und schwerfälligem Swapping durchaus relevant.
Damals dominierten native Apps, nicht so etwas wie Web 2.0 oder NodeJS, und auch Java hatte keinen guten Ruf.
Am Ende wirkte es wie so oft: zwei Schritte vor, einer zurück.
Entgegen dem Unterton, es sei nicht langsam, war es in der Praxis langsam, weniger kompatibel als andere Lösungen, erforderte Neukompilierung und war über den Großteil seiner Lebensdauer kein breit geliebtes Werkzeug.
In
cygwin1.dlllief eine enorme Menge Kompatibilitätszauberei, und letztlich wurde die externe Linux-Mechanik einfach in den Prozess hineingezogen. Besonders wenn man daran denkt, wiefork()ohne Systemunterstützung umgesetzt wurde.Cygwin läuft in einer Windows-AppContainer-Isolation überhaupt nicht. MSYS2 basiert bis heute darauf, daher laufen auch MSYS2-Binärdateien nicht im AppContainer.
Deshalb musste man für das Sandboxen von Claude Code einen völlig anderen Weg gehen. Claude Code erwartet Git for Windows, und Git for Windows verteilt unter anderem
bash.exe, das mit MSYS2 gebaut wurde.Echte native Windows-Builds haben dagegen nicht diese seltsamen Hacks, die
cygwin1.dllverlangt, und die non-MSYS2-Builds, die ich gefunden habe, liefen im AppContainer problemlos.Man kann
pacmanaus Arch Linux nutzen, sodass sich native POSIX-Binärdateien unter Windows auch ohne Linux-VM ziemlich benutzerfreundlich handhaben lassen.Wenn es von einer gewünschten C-Bibliothek keine vorgebaute Cygwin-Version gab, musste man den kompletten Abhängigkeitsbaum selbst mit
configure,makeusw. durchbauen.Und meiner Erinnerung nach musste man dabei in etwa zwei von drei Fällen noch selbst irgendetwas patchen, weil POSIX eben nicht ganz perfekt passte.
Um die korrekten Semantiken nachzubilden, waren aber allerlei Umwege und Hacks nötig; zum Beispiel war
forkkein Copy-on-Write.Ich habe Cygwin ungefähr von 1999 bis 2022 benutzt, WSL2 auch ein wenig, und auf dem Laptop nutze ich es noch immer.
Mein Desktop ist allerdings seit letztem Jahr komplett auf Linux umgezogen.
Früher, in meinen XP-Zeiten unter Windows, habe ich Colinux laufen lassen, und es war wirklich ein faszinierendes Werkzeug.
Einen LAMP-Stack auf der Linux-Seite aufzusetzen war viel einfacher, und mit Windows-Editoren konnte man sich eine ziemlich gute lokale Entwicklungsumgebung bauen.
Man konnte sogar einen X11-Server für Windows anhängen und darauf einen Linux-Desktop laufen lassen.
Als ich merkte, wie ich mir immer mehr Unix-artige Umgebung auf Windows stapelte, bin ich am Ende einfach zu macOS gewechselt.
Abseits des reinen Hack-Werts wirkt es für praktische Zwecke so, als würde man auf einem 486er schnell an Speichergrenzen stoßen.
http://colinux.org/
Nur haben das nicht viele erkannt.
Für mich sah das nach einer nahezu unmöglichen Aufgabe aus.
Mich würde aber interessieren, wie es auf Leute wirkt, die die Architektur verstehen.
Deshalb musste ich an den Witz denken, in dem zwei Mathematiker einen Satz als trivial bezeichnen und erst nach zwei Stunden Erklärung zugeben, dass er tatsächlich trivial ist.
Der Professor meinte nur, ja, stimmt, und wir sind einfach weitergegangen.
Beeindruckend ist vielmehr, dass der Autor nach und nach die lange Liste fast visionsartiger Details herausgearbeitet hat, die so etwas überhaupt möglich machen.
Deshalb kann jedes Programm nur einen Teil seines eigenen Speichers lesen, und auch die CPU steht ihm nur begrenzte Zeit zur Verfügung, bevor zum nächsten Programm gewechselt wird.
Windows begann diese Mechanismen mit Windows NT ernsthaft zu nutzen, und XP gehört zu dieser Linie.
Bei Windows bis 98 konnten Programme dagegen fast alles tun, und die entsprechenden Schutzmechanismen der Hardware lagen im Grunde brach.
Das damalige Windows wirkte deshalb eher wie ein Bündel von Funktionsbibliotheken, das eine UI anzeigt und mit Peripherie spricht, als wie ein echtes Betriebssystem.
Die CPU besitzt spezielle Hardware, um Speicherzugriffe und Rechenzeit zu begrenzen, aber Windows 9x nutzte das nicht vollständig aus.
Genau dadurch entstand wohl Spielraum dafür, dass ein Linux-Subsystem für Windows 9x selbst Betriebssystem spielen und diese Hardware nutzen konnte, um ein modernes Betriebssystem laufen zu lassen.
Der schwierigste Teil solcher Arbeit ist meiner Ansicht nach, die Microsoft-Treiber-API herauszufinden.
Die Dokumentation aus der 9x-Zeit war weder detailliert genug noch leicht zugänglich, und angenehm ist der Bereich auch heute nicht gerade.
Gerade deshalb schien dort genug Raum zu sein, um einige Low-Level-Funktionen von Linux hineinzupflanzen.
Auf der einen Seite hieß es, Show HN habe sich verdreifacht und es gebe immer mehr Apps mit ähnlichem Vibe-Coding-Gefühl, und auf der anderen Seite gräbt sich jemand sechs Jahre lang in Win9x ein, um darin einen modernen Linux-Kernel laufen zu lassen.
Verglichen mit Threads voller Apps, die aus 20-Minuten-Prompts entstanden sind, machte so ein Post einfach glücklich.
So eine Formulierung zu lesen, fand ich ziemlich gut.
Statt „create me an owl app“ ist es wohl üblich geworden, sich einen umfassenden Prompt zum Bau einer Owl-App schreiben zu lassen und den dann in die nächste AI-Session zu kopieren.
Es gibt nämlich tatsächlich ein Produkt namens Zero AI, daher konnte man das auch so lesen.
Das ist deutlich eindeutiger formuliert, und auch das Projekt selbst ist wirklich erstaunlich.
https://codeberg.org/hails/wsl9x
Bei Mastodon muss man zum Lesen eines einzelnen Beitrags immer noch JavaScript ausführen, deshalb ignoriere ich solche Links meistens einfach.
https://github.com/mastodon/mastodon/issues/23153
https://github.com/mastodon/mastodon/issues/19953
Ich kenne nur Bruchstücke wie den VM Monitor und dass es diese Art von Unterstützung gab, aber die eigentlichen Erklärungen scheinen überall verstreut zu sein.
Viele fassen Windows so zusammen, als sei es einfach nur etwas, das auf DOS läuft, aber das ist eindeutig nicht präzise.
Natürlich ist das nicht dasselbe wie eine virtuelle Maschine im heutigen Sinn, aber darin steckte eine ziemlich interessante technische Struktur, und die meisten Quellen behandeln das nur oberflächlich.
Mich würde auch interessieren, wie ähnlich dieses Projekt BSD on Windows ist.
Und Architecture of Windows 9x kenne ich ebenfalls, aber mir fehlte dort Tiefgang.
https://winworldpc.com/product/windows-sdk-ddk/windows-95-ddk
Die Dokumentation ist sehr ausführlich und enthält viele Beispielcodes, sodass sie sich gut zum tieferen Einarbeiten eignet.
Wenn WSL für Linux on Windows steht, könnte man das hier auch als W9xSL im Sinn von Linux auf Windows 9x lesen.
Ich kann es gerade nicht belegen, aber ich meine mich zu erinnern, einmal gelesen zu haben, dass das mit Markenrecht zu tun hatte.
Eigentlich wollte man es wohl Linux Subsystem for Windows nennen, aber die Linux Foundation habe es nicht erlaubt, dass ein nicht autorisiertes Projekt einen Namen benutzt, der mit Linux beginnt.
Die Grundphilosophie bestand darin, mehrere Personalities zu haben, deren Systemaufrufe jeweils in NT-Kernel-Aufrufe übersetzt werden.
In diesem Sinn war WSL1 2016 im Grunde derselbe Trick noch einmal für Linux.
Windows 9x stammte dagegen aus der DOS-Linie, daher brauchte man dort zum Ausführen von Linux wahrscheinlich viel schmutzigere und grundlegend andere Hacks.
Vermutlich hat es damals auch deshalb niemand gemacht.
Dass es hier tatsächlich funktioniert, zeigt für mich, wie weit seiner Zeit voraus die NT-Architektur war.
Als praktischer Anwendungsfall kommen mir Umgebungen in den Sinn, die an Windows 98 gebunden sind, etwa alte medizinische oder industrielle Software.
Wenn man 2026 allerdings einen 486er in der Hand hat, ist es wahrscheinlich weit sinnvoller, einfach natives Linux zu betreiben, statt Linux in eine 30 Jahre alte DOS-Abspaltung hineinzustecken.
Dass Windows 9x DOS ausführen konnte, war an sich schon mit ziemlich viel Magie verbunden.
Dazu gibt es auch lesenswerte Beiträge:
Ach, coLinux, haha -_- ein vertrauter Name. Haha, aber aktuell nutze ich selbst mit WSL nichts davon, doch
win95+linuxklingt schon verlockend.