PythonOS: Een bare-metal besturingssysteem met CPython 3.14 als kernel
Het systeem boot direct naar een >>> prompt op de seriële console. De interactieve prompt is een echte Python REPL waarin functies en klassen gedefinieerd kunnen worden, bestanden uit /examples of /home geïmporteerd kunnen worden, en de geschiedenis kan worden teruggevonden met de pijl-omhoog toets (dit wordt bewaard over reboots heen op de ext2 mount).
Er is een optionele GUI-desktop beschikbaar met een stacking compositor, een PySDL2-compatibele Python API, PNG/JPEG-decoders, een audio-mixer, configureerbare toetscombinaties, een prestatiebewaker, een macOS-stijl menubalk (PythonOS / Apps / Demos / Games), een gepolijste desktopachtergrond en een dock met gebundelde apps. Demos en games kunnen worden gestart via een twee-vinger-klik of control-klik op het behang (of via de menu's Demos en Games); ze verschijnen in het dock alleen tijdens het uitvoeren, tenzij de optie 'Keep in Dock' is gekozen.
Gebruik make help voor een overzicht van alle top-level targets.
Snelstart
Voorwaarden
- Docker (voor de cross-compilatie toolchain)
- QEMU (
brew install qemuop macOS) - CPython 3.14 broncode (wordt automatisch opgehaald tijdens het bouwen)
Eerste build (ongeveer 10 minuten voor cross-compilatie van CPython)
make docker-build # Bouw eenmalig het Docker cross-compilatie image
make # Cross-compileer libpython + kernel, produceert build/pythonos.iso
Latere builds (snel, aangezien libpython gecached is)
make # Bouw kernel + ISO opnieuw als bronbestanden zijn gewijzigd
Uitvoeren
# Standaard boot — seriële REPL, geen GUI-venster. Detecteert automatisch host-architectuur.
make run
# x86_64 CPU-aantal staat standaard op 2; override indien nodig
SMP_CPUS=4 make run
# Experimentele x86_64 CPython free-threading build
PYTHONOS_FREE_THREADING=1 make cleanall all
# Specifieke vormen per architectuur:
make run-x86_64
make run-arm64
# Een draaiende instantie stoppen
make stop
make stop-arm64
Gebruik Ctrl-A X om QEMU te verlaten.
GUI Modus
De optionele grafische desktop bevat een stacking compositor, een macOS-stijl menubalk, een aangepaste achtergrondafbeelding, muis- en toetsenbordinput, audio-output en gebundelde dock-apps. De standaard make run en make test paden blijven ongewijzigd en booten alleen serieel met -nographic.
Een software chipset laboratorium (kernel.chipset) kan de scan overnemen: Dit bevat copper lists, dual playfields, acht sprites, een blitter en vier Paula audio-kanalen — volledig geschreven in Python. Dit is een optionele API voor first-principles en de demoscene, niet de normale applicatie-toolkit. Gewone vensters en games gebruiken de SDL-compatibele surface/input API en de algemene systeem-mixer; defender is het referentiegame op dit pad. Chipset-studies omvatten sprites, pacmaze, raiders, invaders en toaster. ESC keert terug naar Workbench.
make test-chipset voert de host-side chipset-, arcade- en dock-tests uit zonder QEMU.
Opstarten met GUI
# Boot en start automatisch de zichtbare host-desktop in één stap.
make run-gui
# Specifieke applicaties starten:
PYTHONOS_GUI_APP=terminal make run-gui
PYTHONOS_GUI_APP=editor make run-gui
PYTHONOS_GUI_APP=files make run-gui
PYTHONOS_GUI_APP=image_viewer make run-gui
PYTHONOS_GUI_APP=top make run-gui
PYTHONOS_GUI_APP=keybindings make run-gui
PYTHONOS_GUI_APP=audio_tone make run-gui
PYTHONOS_GUI_APP=sprites make run-gui
PYTHONOS_GUI_APP=defender make run-gui
PYTHONOS_GUI_APP=pacmaze make run-gui
PYTHONOS_GUI_APP=raiders make run-gui
PYTHONOS_GUI_APP=toaster make run-gui
Dezelfde launcher is beschikbaar binnen elke PythonOS REPL:
desktop(): Opent de desktop.desktop('naam'): Start een specifiek gebundeld programma.desktop('help'): Lijst alles op wat in de interpreter is bevroren.
In de $ sub-shell kan desktop, desktop pacmaze of desktop --list worden gebruikt. Het oudere commando pythonos_gui blijft beschikbaar als compatibiliteitsnaam voor de directe framebuffer backend.
Interactie binnen de compositor
- F1: Opent Keybindings; kies een rij en druk op Enter om een snelkoppeling te vervangen.
- F2: Opent de live broncode van het geselecteerde venster. (Beide shortcuts zijn configureerbaar).
- Tab / Shift-Tab: Wisselt de focus tussen vensters.
- Titelbalk: Klik en sleep om het venster te verplaatsen.
- Body: Klik om focus te krijgen en het venster naar voren te halen.
- Import: Sleep een host-bestand overal naartoe om het in
/homete importeren, of naar een directory in 'Files' om het daar te importeren. - Export: Sleep een PythonOS-bestandsrij naar 'Export' om het te kopiëren naar de Downloads-map van de hostmachine (wijzigbaar via
PYTHONOSEXPORTDIR). - ESC: Sluit doorgaans de gefocuste app en keert terug naar de REPL.
De Image Viewer start in /examples/images, wat drie originele slang-thema PNG's bevat in fotografische, pixel-art en wetenschappelijke illustratiestijlen. Het chipset-curriculum bevindt zich onder /examples/graphics/chipset. Zie docs/gui.md voor de volledige referentie.
Remote Display: Kernel op X, Desktop op Y
Het desktop-protocol is TCP en vereist niet dat QEMU en SDL op dezelfde computer draaien.
Machine X (de kernel host):
# Beperk het bind-adres indien mogelijk.
PYTHONOS_DISPLAY_BIND=0.0.0.0 make run-display-server
Machine Y (de display host): Vereist alleen de repository en SDL-afhankelijkheden voor de kleine bridge-binary.
make bridge
PYTHONOS_DISPLAY_SERVER=192.0.2.10 make connect-display
# Optionele bestemming voor geëxporteerde bestanden:
PYTHONOS_EXPORT_DIR="$HOME/Desktop/PythonOS" \
PYTHONOS_DISPLAY_SERVER=192.0.2.10 make connect-display
Dit is analoog aan een netwerkdisplay, hoewel de verbindingsrichting momenteel desktop-naar-kernel is. Het protocol heeft momenteel geen authenticatie of encryptie. Gebruik dit alleen op een vertrouwde netwerkverbinding.
Native Debugsessies
Voor fouten in de kernel, HAL, CPython, interrupts of netwerking, start een agent-debug sessie:
# Zichtbare user-facing debug desktop.
PYTHONOS_DEBUG=1 PYTHONOS_DESKTOP_MODE=interactive make run-gui
# Verborgen/offscreen desktop voor agent-automatisering, captures en benchmarks.
PYTHONOS_DEBUG=1 PYTHONOS_DESKTOP_MODE=headless make run-gui
Gebruik vervolgens de debug-tools:
python3 tools/pythonos_debug.py serialpython3 tools/pythonos_debug.py qmp statuspython3 tools/pythonos_debug.py native -- "bt" "info registers"python3 tools/pythonos_debug.py exercise paintpython3 tools/pythonos_debug.py perfpython3 tools/pythonos_debug.py capture build/pythonos-debug.bmppython3 tools/pythonos_debug.py desktop statuspython3 tools/pythonos_debug.py desktop metrics
Dit creëert build/pythonos-debug.json met details over de loopback-only TCP REPL, een native remote endpoint, een QMP-control socket, symbol ELF en een persistente seriële log. PYTHONOSDEBUGPAUSE=1 pauzeert vóór uitvoering voor debugging tijdens het vroege bootproces.
No-GIL Build
De no-GIL build wordt momenteel ondersteund op x8664 QEMU met SMP ingeschakeld. Het boot CPython met PYGIL_DISABLED=1 en gebruikt een kleine mmap-shim die vaste mappings valideert voordat er geheugen wordt aangeraakt. Native threads zijn momenteel worker-dispatches op geïnitialiseerde AP's, geen volledige scheduler voor willekeurige blokkerende POSIX-workloads.
Connecteren naar de TCP REPL
Zodra de kernel draait, luistert een multi-sessie Python REPL op TCP-poort 5000 binnen QEMU. QEMU stuurt dit door naar de host:
- x86_64:
nc localhost 5555 - arm64:
nc localhost 5556
Elke verbinding krijgt een onafhankelijke kernel-shell met toegang tot alle live kernel-objecten. Meerdere sessies kunnen gelijktijdig draaien; Python is de kernel, en concurrency wordt afgehandeld via asyncio, niet via fork/exec.
PythonOS Kernel Shell
PythonOS kernel shell
Python 3.14.0a0
Type help or help() for commands, demos, and examples.
Commands: ls ps pwd cd cat cp mv ftp ed sysinfo netstat
Desktop: desktop() desktop('pacmaze') desktop('help')
Examples: examples() run('/examples/start_here/hello_kernel.py')
Helpers: sh() sh('cmd args') run('/path') clear()
>>> 1 + 1
2
>>> sysinfo
PythonOS
Scheduler: 3 tasks
cwd: /
>>> ls /bin
. .. ls.py ps.py pwd.py cd.py cat.py cp.py mv.py ftp.py ed.py sysinfo.py netstat.py desktop.py examples.py
>>> cd /tmp
>>> pwd
/tmp
>>> sh()
PythonOS shell: help | examples | desktop [APP] | exit
$ sysinfo
PythonOS
Scheduler: 3 tasks
cwd: /tmp
$ ls
. ..
$ exit
>>> import kernel.log as log; log.info("hello from REPL")
Unix-achtige Shell Ervaring
De kernel-shell biedt een Unix-achtige commando-ervaring genest binnen de Python REPL.
Bare-word Command Dispatch
Elke identifier die wordt getypt bij >>> en die geen bestaande Python-naam is, wordt opgezocht als /bin/<naam>.py en automatisch uitgevoerd. Er is geen run(), geen aanhalingstekens en geen .py extensie nodig:
>>> ls
>>> ls /bin
>>> ps
>>> pwd
>>> cd /tmp
>>> cat /examples/README.txt
>>> ed /tmp/notes.txt
>>> sysinfo
>>> netstat
Argumenten worden gesplitst op witruimte en als argv aan het script doorgegeven:
>>> cp /bin/sysinfo.py /tmp/my_sysinfo.py
>>> mv /tmp/my_sysinfo.py /tmp/sysinfo_backup.py
>>> ftp get /tmp/host-file.txt
>>> ftp put /tmp/host-file.txt
Ingebouwde Commando's
| Commando | Beschrijving |
|---|---|
ls [pad] | Lijst directory op (standaard: huidige werkdirectory) |
ps | Lijst kernel-taken op met PID, naam, status |
pwd | Print de huidige werkdirectory |
cd [pad] | Wijzig directory (ondersteunt .., relatieve paden; standaard: /) |
cat BESTAND [...] | Print inhoud van bestanden |
cp BRON BESTEMMING | Kopieer een bestand |
mv BRON BESTEMMING | Verplaats of hernoem een bestand |
ftp get BESTEMMING [POORT] | Ontvang één TCP-bestandsstroom in TmpFS |
ftp put BRON [HOST] [POORT] | Verstuur één TmpFS-bestand over TCP |
ed [pad] | Line-editor in de stijl van ed |
sysinfo | Systeemoverzicht |
netstat | Status van netwerkinterfaces |
desktop [APP] | Open de desktop, optioneel met een gebundelde app, demo of game |
examples | Lijst de leesbare programma's op die in /examples zijn bevroren |
Shell sub-REPL: sh()
Door sh() zonder argumenten aan te roepen, kom je in een interactieve shell met een $ prompt. Deze gebruikt dezelfde /bin/*.py commando's en deelt de cwd (current working directory) status met de parent-sessie. Type exit om terug te keren naar >>>.
>>> sh()
PythonOS shell: help | examples | desktop [APP] | exit
$ ls /bin
. .. ls.py ps.py pwd.py cd.py cat.py cp.py mv.py ftp.py ed.py sysinfo.py netstat.py desktop.py examples.py
$ cd /tmp
$ pwd
/tmp
$ help
$ examples
$ desktop --list
$ /examples/audio/tone.py
$ exit
>>> cwd
'/tmp'
Binnen sh() worden .py paden direct uitgevoerd. sh('cmd args') is de single-shot vorm voor scripting:
>>> sh('cp /bin/sysinfo.py /tmp/backup.py')
>>> sh('ls /tmp')
>>> sh('/examples/audio/tone.py')
Eigen commando's schrijven
Elk .py bestand in /bin/ wordt automatisch een shell-commando. Scripts draaien in de kernel-namespace; vfs, scheduler, pci, net, OpenFlags en print zijn vooraf gebonden. Top-level await wordt ondersteund.
Voorbeeld /bin/mycommand.py:
# Uitgevoerd door te typen: mycommand arg1 arg2
path = argv[0] if argv else cwd
entries = await vfs.readdir(path)
for e in entries:
print(e)
argv is een lijst met string-argumenten. cwd is de huidige werkdirectory; een script kan dit bijwerken (cwd = '/new/path') en de shell neemt deze wijziging over.
Je kunt ook runtime een nieuw commando maken:
>>> fd = await vfs.open('/bin/hello.py', OpenFlags.WRONLY | OpenFlags.CREAT | OpenFlags.TRUNC)
>>> await vfs.write(fd, b"print('hello, ' + (argv[0] if argv else 'world'))\n")
>>> vfs.close(fd)
>>> hello
hello, world
>>> hello PythonOS
hello, PythonOS
Voorbeeldprogramma's
PythonOS bevat in /examples leesbare Python-programma's die als bytecode in de kernel zijn bevroren. Hierdoor kunnen ze normale functies, klassen, async loops en imports gebruiken zonder afhankelijk te zijn van de beperkte runtime-compiler.
>>> ls /examples
README.txt start_here/ storage/ concurrency/ graphics/ images/ audio/
networking/ demos/ games/ internals/
>>> examples()
PythonOS learning tracks in /examples:
>>> run('/examples/start_here/hello_kernel.py')
>>> run('/examples/storage/vfs_demo.py')
>>> run('/examples/concurrency/async_tasks.py')
>>> sh('/examples/start_here/primes.py 100')
>>> run('/examples/audio/tone.py')
Elke directory heeft een README met een geordend pad en concepten. /internals/ bevat executable kernel-validatie fixtures; /demos/ en /games/ bevatten de broncode van de desktop-applicaties.
Speciale commando's
ed: Een line-oriented editor geïnspireerd doorpy_ed. Ondersteunt append/insert/change/delete, print/number/literal print, marks, move/copy, read/write/write-append, one-level undo en q/Q.ftp: Een eenvoudige tool voor het kopiëren van bestanden over een ruwe TCP-stroom (geen RFC FTP).- Inbound naar PythonOS:
>>> ftp get /tmp/inbox.txt(Host:nc localhost 17000 < local-file.txt). - Outbound vanaf PythonOS:
>>> ftp put /tmp/inbox.txt(Host:nc -l 7001 > from-pythonos.txt).
Mixen van Python en Shell
De twee modi zijn additief. Alles wat een geldige Python-expressie of statement is, gaat via de Python-interpreter. Shell-dispatch vuurt alleen af voor bare identifiers die nog niet in de Python-namespace staan.
>>> ls # shell dispatch → /bin/ls.py
>>> list(pci) # Python expressie → PCI apparaatlijst
>>> for d in pci: print(d) # Python statement → loop over PCI bus
>>> sh() # enter shell sub-REPL
$ ps # shell commando
$ exit # return naar >>>
>>> scheduler.ps() # terug naar Python
Seriële Shell
De >>> prompt is ook beschikbaar op de seriële console (het QEMU terminal-venster zelf). Alle interactieve I/O verloopt via COM1 (x86_64) of PL011 (arm64).
Smoke Tests uitvoeren
make test: Standaard boot smoke test (gebaseerd op seriële + TCP REPL).make test-gui: GUI-subsystem smoke test (headless screendump + audio capture).
make test boot PythonOS in QEMU als een subprocess, wacht tot de TCP REPL bereikbaar is, voert een reeks Python-expressies uit, verifieert de output en sluit af.
make test-gui voert op x86_64 drie extra suites uit:
- GUI smoke: sdl2 corpus, compositor render, mouse pipeline, pointer round-trip, seriële markers.
- Desktop smoke: boot, start
desktop('bouncing_ball'), screendumps en verifieert pixel-exacte achtergrond, titelbalk en vensters. - Audio smoke: boot met
-audiodev wav, voertexamples/audio/tone.pyuit en verifieert de WAV-header (48 kHz / 2ch / 16-bit).
In totaal zijn er 137 tests over zes suites. GitHub Actions draait deze tests op zowel ubuntu-24.04 (x86) als ubuntu-24.04-arm.
Wat is dit precies?
De meeste besturingssystemen zijn geschreven in C, met scriptingtalen die als userspace-programma's erbovenop zijn geplaatst. PythonOS draait dit om: de Python-interpreter is de kernel-primitieve. Er is geen C-runtime die Python beheert — Python beheert de machine.
De filosofische aanname is dat "alles is een object" een beter organiserend principe is voor een kernel dan "alles is een bestand". importlib, exec en inspect worden de syscalls voor hot-reload en introspectie van het OS. Het systeem kan zichzelf tijdens runtime uitbreiden zonder te rebooten.
Bootvolgorde
x86_64
- GRUB2 (multiboot2)
- boot.asm — long mode, 4 GiB identity map, 4 MiB stack
- main.c — GDT, IDT, PIC (8259A), PIT (100 Hz), COM1 serial
- kthread.c — bootstrap-CPU native thread self-test
- smp.c — ACPI MADT discovery, AP startup, per-CPU state, native AP worker dispatch
- hal.c — CPython init, freeze frozen modules
- kernel.boot() — Python neemt de machine over:
- PMM + VMM
- PCI enumeratie + driver binding (VirtIO-net, Intel HDA)
- asyncio event loop (PIT-driven, 100 Hz)
- Network stack (ARP/IP/TCP)
- TCP REPL server (poort 5000, multi-sessie)
- COM1 seriële input driver
- Interactieve kernel shell (serieel + TCP)
arm64 (QEMU virt)
- U-Boot / QEMU direct kernel load
- boot_arm64.asm — EL1, MMU off, 4 MiB stack
- main_arm64.c — GIC v2, generic timer (100 Hz), PL011 serial
- hal.c — CPython init, freeze frozen modules
- kernel.boot() — Python neemt de machine over:
- PMM + VMM
- VirtIO-MMIO block device (raw disk image)
- asyncio event loop (GIC timer-driven)
- PL011 seriële input driver
- Interactieve kernel shell (serieel)
Verwachte Boot Output (x86_64)
[PythonOS] INFO kernel.boot: interrupt router connected
[PythonOS] INFO kernel.boot: PMM ready — 510 MiB free
[PythonOS] INFO kernel.boot: VMM ready
[PythonOS] INFO kernel.boot: enumerating PCI bus...
[PythonOS] INFO kernel.boot: 7 PCI devices found
[PythonOS] INFO kernel.boot: tmpfs mounted at /
[PythonOS] INFO kernel.boot: event loop ready
[PythonOS] INFO kernel: no framebuffer — serial only
[PythonOS] INFO kernel: COM1 serial input ready
[PythonOS] INFO virtio-net: MAC 52:54:00:12:34:56
[PythonOS] INFO kernel: network stack starting
[PythonOS] INFO repl: TCP REPL listening on port 5000 — connect: nc localhost 5555
[PythonOS] INFO kernel: HDA sound ready
[PythonOS] INFO mixer: attached backend HDADriver
[PythonOS] INFO kernel: shell spawned — system ready
PythonOS kernel shell
Python 3.14.0
...
>>>
Broncode-indeling
src/
- boot/: ASM + C bootstrap (GDT, IDT, PIC, PIT, serial, framebuffer x86_64; GIC, timer, PL011 arm64).
- hal/:
hal.c—_halPython C-extensie (port I/O, MMIO, interrupts, DMA). - libc/: Freestanding libc (buddy allocator, string, stdio, POSIX stubs).
- linker.ld / linker_arm64.ld: ELF layouts.
kernel/
- \\init\\.py:
boot()entry point. - hal/: Dunne Python wrapper over
_hal. - interrupts/: Interrupt router,
@interruptdecorator, default handlers. - bus/pci.py: PCI enumeratie, driver Protocol, PCIBus.
- display/: Framebuffer + bitmap font console.
- log.py: Seriële logging via
_hal. - memory/: PMM (page frame allocator), VMM (virtual address spaces).
- drivers/:
- input/: COM1, PL011, virtio-input, keyboard, mouse.
- net/:
virtio_net.py(DMA descriptor rings). - block/:
virtio_blk.py(arm64). - display/:
bochs.py(x86 GUI),ramfb.py(arm64). - sound/:
virtio_snd.py(arm64),hda.py(Intel HDA),mixer.py(PCM playback API). - gui/: GUI subsystem (optioneel):
input.py: Event + EventQueue.compositor.py: Stacking window manager.sdl2/: PySDL2-compatibele Python API.image/: Decoders voor BMP, PPM, PNG, JPEG.- net/: Ethernet, ARP, IP, TCP state machine, stack init, TCP REPL server.
- fs/: VFS (POSIX-like fd table, async protocol) + tmpfs.
- ed.py: Line-editor voor
/bin/ed.py. - scheduler.py: asyncio task scheduler.
- shell.py: Kernel shell (REPL +
/bindispatch +sh()sub-REPL).
apps/
GUI-applicaties: terminal, editor, files, imageviewer, sysmon, keybindings, about, clock en diverse demos (bouncing\ball, audio\_tone, starfield, etc.).
bin/
Shell-commando's: ls.py, ps.py, pwd.py, cd.py, cat.py, cp.py, mv.py, ftp.py, ed.py, sysinfo.py, netstat.py, desktop.py, examples.py.
examples/
Educatieve tracks: start_here/, storage/, concurrency/, graphics/, audio/, networking/, demos/, games/, internals/.
asyncio/
Bare-metal implementatie van de asyncio API (Future, Task, Queue, Event, Lock, Semaphore, etc.) zonder sockets of selectors.
tests/
Smoke tests voor x86, arm64, GUI, desktop en audio.
tools/
freeze_kernel.py: Compileert kernel + apps + examples naar bevroren C bytecode.run_gui.py: Superviseert QEMU + bridge.stdlib_stubs/: Bare-metal vervangers voor stdlib-modules (bijv.os,dataclasses,functools).
Architectuurnotities
CPython on Bare Metal
CPython 3.14.0 is gecompileerd als een statische library (libpython3.14.a) en direct gelinkt in de kernel ELF. Py_Initialize() draait vóór elke Python-code; vanaf dat moment is de Python-interpreter de kernel runtime. Alle kernel-modules zijn "bevroren" (bytecode in de ELF) zodat er geen filesystem nodig is voor imports.
_hal C-Extensie
De _hal module biedt directe hardware-toegang:
| Functie | Beschrijving |
|---|---|
inb/inw/inl(port) | Port I/O reads (x86_64) |
outb/outw/outl(port, val) | Port I/O writes (x86_64) |
mmio_read8/32(addr) | Memory-mapped I/O reads |
mmio_write8/32(addr, val) | Memory-mapped I/O writes |
dma_alloc(size) | Alloceert DMA-buffer uit de C-heap, geeft fysiek adres terug |
buf_addr(bytearray) | Geeft fysiek adres van internal buffer van bytearray |
read_cr2/cr3() | Control register reads (x86_64) |
setinterruptrouter(fn) | Registreert Python interrupt dispatcher |
seteventloop(loop) | Registreert asyncio loop voor interrupt-safe dispatch |
ARCH | String constant: "x86_64" of "arm64" |
DMA Geheugen
De Python garbage collector mag DMA-buffers nooit aanraken. hal.dmaalloc(n) alloceert vanuit de C buddy allocator (calloc), waardoor de GC de allocatie niet ziet. Dit wordt gebruikt voor VirtIO-net descriptor rings en HDA BDLs.
Bare-Metal asyncio
De asyncio/ package is een from-scratch implementatie. De event loop wordt aangedreven door de PIT timer (x8664) of GIC timer (arm64) op 100 Hz. Hardware interrupt callbacks worden gerouteerd via callsoon_threadsafe.
Multi-Sessie TCP REPL
De REPL server luistert op poort 5000. Elke nieuwe verbinding start een nieuwe asyncio task met een onafhankelijke Shell-instantie. Alle sessies delen dezelfde live kernel-namespace (scheduler, vfs, pci\_bus, etc.) omdat ze coroutines zijn binnen hetzelfde Python-proces dat de kernel is.
Stdlib Stubs
Verschillende stdlib-modules gaan uit van een POSIX-host. In tools/stdlib_stubs/ staan vervangers:
dataclasses.py: Herschreven met closures omdat de originele versieexec()gebruikt.functools.py:_CacheInfovervangen door een gewone klasse.os.py: Minimale stub.ctypes/init.py: Minimale stub vooraddressof.random.py: Minimale LCG PRNG, seeded vanaf PIT port reads.traceback.py: Minimaleformat_exc.
De (volledig ware en totaal niet aangedikte) geschiedenis van PythonOS
De voortdurende avonturen van Jordan Hubbard en Sir Reginald von Fluffington III.
Het begon, zoals veel projecten van programmeurs, met een zin die op dat moment volkomen redelijk klonk: "De kernel," kondigde hij aan tegen de woonkamer, "zou in Python geschreven moeten worden."
Sir Reginald von Fluffington III sliep op een exemplaar van Modern Operating Systems. Hij opende zijn ogen niet, maar liet één oor ongeveer vier graden zakken — het katten-equivalent van een opgetrokken wenkbrauw — voordat hij terugkeerde naar de serieuze zaak van het bewusteloos zijn. De programmeur zag dit als aanmoediging.
Het idee was niet nieuw. MicroPython bestond al. Maar Python draaien als het besturingssysteem — als de interrupt handler, de memory manager, de scheduler, het bestandssysteem, de netwerkstack — dat was een andere claim. De programmeur noemde het "elegant". Sir Reginald, die dit woord al had horen toepassen op zeventien eerdere beslissingen van wisselende kwaliteit, update een privédagboek onder de kop "Hubris, Algemeen".
Het eerste probleem was CPython zelf. De interpreter verwachtte een POSIX-host; hij verwachtte fork en select. De programmeur bracht weken door met het schrijven van configure-flags om deze verwachtingen één voor één te verwijderen, als een zorgvuldige redacteur die elke aanname dat er beschaving bestaat, weghaalt. Het resultaat was libpython3.14.a: een statische library zonder elke syscall waar hij ooit op had vertrouwd, direct gelinkt in de kernel ELF.
"Geen socket. Geen readline. Geen fork," vertelde de programmeur aan Sir Reginald, terwijl hij de Modules.Setup.local als een trofee presenteerde. Sir Reginald inspecteerde deze door erop te gaan zitten. Daarna ging hij op het toetsenbord zitten. De programmeur interpreteerde dit als een verzoek om een demonstratie, verschoof de kat, opende een terminal en typte make run.
De kernel bootte. Python initialiseerde. De >>> prompt verscheen op de seriële console. Sir Reginald, die zich had verplaatst naar de kabelroutering achter de monitor, was niet beschikbaar voor commentaar.
Wat het project echt vreemd maakte, was het interrupt-model. In een normaal OS worden hardware-interrupts afgehandeld in C. In PythonOS handelt de C bootstrap de raw vector af en roept onmiddellijk asyncio.geteventloop().callsoonthreadsafe(interrupt_router, vector) aan — en vanaf dat moment neemt Python het over. De PIT timer vuurt 100 keer per seconde. De scheduler is asyncio. De kernel shell is await shell.run(). Het hele besturingssysteem is, tijdens runtime, een set coroutines.
Sir Reginald was hier niet onder de indruk van. Hij had de programmeur al eens asynchrone code schrijven zien maken en wist waar dat op uitliep: om twee uur 's nachts debuggen met asyncio.ensure_future terwijl hij mompelde over de event loop.
De arm64-port vereiste een aparte omweg. QEMU's virt-machine heeft geen PCI-bus, alleen VirtIO-MMIO, een GIC interrupt controller en een PL011 UART. De programmeur portte de timer, de seriële driver en het block device door secties van de ARM Architecture Reference Manual te lezen die Sir Reginald structureel identiek vond aan de eerdere lectuur over besturingssystemen: beide hielden in dat er grote boeken aan te pas kwamen en dat er geen tonijn uit voortkwam.
De TCP REPL was het onderdeel waar de programmeur het meest trots op was. Na het vanaf nul bouwen van een TCP-stack — ARP-resolutie, IPv4, een basis TCP state machine — koppelde hij dit aan de kernel shell op poort 5000. Meerdere sessies konden gelijktijdig draaien en deelden dezelfde live kernel-objecten.
"Dit," zei de programmeur, "bewijst dat Python een echt multitasking-kernel is."
Sir Reginald liep over het toetsenbord. De shell printte TypeError: unsupported operand en beëindigde. De programmeur noteerde dat dit een aparte bug was en rapporteerde deze dienovereenkomstig.
De smoke test werd als laatste toegevoegd. tests/smoke_test.py boot de ISO, wacht tot de TCP REPL bereikbaar is en verifieert dat 1 + 1 gelijk is aan 2, dat vfs niet None is, en dat 1 / 0 een ZeroDivisionError veroorzaakt. Sir Reginald heeft nooit make test uitgevoerd. Hij is echter twee keer op de test-output gaan zitten, wat de programmeur telt als een code review.
Tegen de tijd van schrijven is PythonOS in productie gebruikt door precies één persoon, die het ook heeft geschreven. Sir Reginald weigert zijn goedkeuring voor alle zes de projecten, met als redenen "procedurele zorgen", "onvoldoende tonijn", "een algemene sfeer van hubris" en, recentelijk, "de fundamentele onserieusheid van een besturingssysteem dat kan worden onderbroken door de garbage collector."
Licentie
BSD 2-Clause. Zie LICENSE.
Groetjes,