fromscratch-pyos 0.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fromscratch_pyos-0.3.0.dist-info/METADATA +205 -0
- fromscratch_pyos-0.3.0.dist-info/RECORD +77 -0
- fromscratch_pyos-0.3.0.dist-info/WHEEL +4 -0
- fromscratch_pyos-0.3.0.dist-info/entry_points.txt +4 -0
- fromscratch_pyos-0.3.0.dist-info/licenses/LICENSE +21 -0
- py_os/__init__.py +1 -0
- py_os/__main__.py +5 -0
- py_os/_version.py +24 -0
- py_os/bootloader.py +219 -0
- py_os/completer.py +233 -0
- py_os/containers.py +328 -0
- py_os/env.py +64 -0
- py_os/fs/__init__.py +39 -0
- py_os/fs/fd.py +163 -0
- py_os/fs/filesystem.py +591 -0
- py_os/fs/journal.py +537 -0
- py_os/fs/persistence.py +94 -0
- py_os/fs/procfs.py +329 -0
- py_os/io/__init__.py +91 -0
- py_os/io/bridge.py +327 -0
- py_os/io/devices.py +193 -0
- py_os/io/disk.py +222 -0
- py_os/io/dns.py +111 -0
- py_os/io/framebuffer.py +185 -0
- py_os/io/http.py +282 -0
- py_os/io/interrupts.py +305 -0
- py_os/io/ipc.py +137 -0
- py_os/io/networking.py +301 -0
- py_os/io/shm.py +54 -0
- py_os/io/tcp.py +830 -0
- py_os/io/timer.py +148 -0
- py_os/jobs.py +104 -0
- py_os/kernel.py +3668 -0
- py_os/logging.py +121 -0
- py_os/memory/__init__.py +38 -0
- py_os/memory/manager.py +225 -0
- py_os/memory/mmap.py +52 -0
- py_os/memory/slab.py +481 -0
- py_os/memory/swap.py +438 -0
- py_os/memory/virtual.py +243 -0
- py_os/process/__init__.py +46 -0
- py_os/process/binary.py +389 -0
- py_os/process/pcb.py +382 -0
- py_os/process/scheduler.py +796 -0
- py_os/process/signals.py +93 -0
- py_os/process/threads.py +146 -0
- py_os/py.typed +0 -0
- py_os/repl.py +114 -0
- py_os/shell/__init__.py +64 -0
- py_os/shell/base.py +559 -0
- py_os/shell/commands/__init__.py +25 -0
- py_os/shell/commands/basics.py +106 -0
- py_os/shell/commands/devices.py +375 -0
- py_os/shell/commands/files.py +505 -0
- py_os/shell/commands/isolation.py +272 -0
- py_os/shell/commands/learn.py +31 -0
- py_os/shell/commands/memory.py +485 -0
- py_os/shell/commands/network.py +765 -0
- py_os/shell/commands/processes.py +1035 -0
- py_os/shell/commands/sync.py +460 -0
- py_os/shell/commands/users.py +131 -0
- py_os/sync/__init__.py +30 -0
- py_os/sync/deadlock.py +265 -0
- py_os/sync/inheritance.py +189 -0
- py_os/sync/ordering.py +227 -0
- py_os/sync/primitives.py +725 -0
- py_os/syscalls.py +2502 -0
- py_os/tui/__init__.py +5 -0
- py_os/tui/app.py +127 -0
- py_os/tui/widgets.py +146 -0
- py_os/tutorials.py +783 -0
- py_os/users.py +472 -0
- py_os/web/__init__.py +14 -0
- py_os/web/app.py +92 -0
- py_os/web/static/style.css +77 -0
- py_os/web/static/terminal.js +65 -0
- py_os/web/templates/index.html +21 -0
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: fromscratch-pyos
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: A simulated operating system built in Python for learning OS concepts
|
|
5
|
+
Project-URL: Homepage, https://github.com/robcox2910/py-os
|
|
6
|
+
Project-URL: Repository, https://github.com/robcox2910/py-os
|
|
7
|
+
Project-URL: Issues, https://github.com/robcox2910/py-os/issues
|
|
8
|
+
Project-URL: Documentation, https://robcox2910.github.io/py-os/
|
|
9
|
+
Author: Rob Cox
|
|
10
|
+
License: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: education,learning,operating-system,os-concepts,simulator
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Education
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
18
|
+
Classifier: Topic :: Education
|
|
19
|
+
Classifier: Topic :: System :: Operating System
|
|
20
|
+
Classifier: Typing :: Typed
|
|
21
|
+
Requires-Python: >=3.14
|
|
22
|
+
Provides-Extra: dev
|
|
23
|
+
Requires-Dist: commitizen>=4.4.0; extra == 'dev'
|
|
24
|
+
Requires-Dist: hypothesis>=6.170; extra == 'dev'
|
|
25
|
+
Requires-Dist: pip-audit>=2.10.0; extra == 'dev'
|
|
26
|
+
Requires-Dist: pre-commit>=4.0.1; extra == 'dev'
|
|
27
|
+
Requires-Dist: pyright>=1.1.400; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest-cov>=6.0.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: pytest>=8.3.4; extra == 'dev'
|
|
31
|
+
Requires-Dist: ruff>=0.9.3; extra == 'dev'
|
|
32
|
+
Provides-Extra: docs
|
|
33
|
+
Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
|
|
34
|
+
Provides-Extra: tui
|
|
35
|
+
Requires-Dist: textual>=0.90; extra == 'tui'
|
|
36
|
+
Provides-Extra: web
|
|
37
|
+
Requires-Dist: flask>=3.0; extra == 'web'
|
|
38
|
+
Description-Content-Type: text/markdown
|
|
39
|
+
|
|
40
|
+
# PyOS
|
|
41
|
+
|
|
42
|
+
**Build your own operating system in Python -- then play with it.**
|
|
43
|
+
|
|
44
|
+
[](https://www.python.org/downloads/)
|
|
45
|
+
[](https://github.com/robcox2910/py-os/actions/workflows/ci.yml)
|
|
46
|
+
[](https://robcox2910.github.io/py-os/)
|
|
47
|
+
[](LICENSE)
|
|
48
|
+
|
|
49
|
+
Ever wondered what happens when you open a program, save a file, or connect to the internet? PyOS is a complete operating system simulator that lets you see every piece -- processes, memory, filesystems, networking -- and poke at them from a real shell. Built with test-driven development and written for learners.
|
|
50
|
+
|
|
51
|
+
## What Does It Look Like?
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
======================================
|
|
55
|
+
PyOS v0.1.0
|
|
56
|
+
A simulated operating system
|
|
57
|
+
======================================
|
|
58
|
+
|
|
59
|
+
[POST] CPU ... OK
|
|
60
|
+
[POST] Memory ... OK
|
|
61
|
+
[POST] Storage ... OK
|
|
62
|
+
[BOOT] Loading kernel image v0.1.0 ... OK
|
|
63
|
+
[OK] Logger
|
|
64
|
+
[OK] Memory manager (256 frames)
|
|
65
|
+
[OK] Slab allocator
|
|
66
|
+
[OK] File system (journaled)
|
|
67
|
+
[OK] Scheduler (FCFS)
|
|
68
|
+
[OK] Init process (PID 1)
|
|
69
|
+
|
|
70
|
+
Kernel running. Type 'help' for commands, 'exit' to quit.
|
|
71
|
+
|
|
72
|
+
root@pyos $ ps
|
|
73
|
+
PID State Name
|
|
74
|
+
1 READY init
|
|
75
|
+
|
|
76
|
+
root@pyos $ fork 1
|
|
77
|
+
Forked process 1 → child PID 2 (init)
|
|
78
|
+
|
|
79
|
+
root@pyos $ pstree
|
|
80
|
+
init (PID 1)
|
|
81
|
+
└── init (PID 2)
|
|
82
|
+
|
|
83
|
+
root@pyos $ learn
|
|
84
|
+
Available tutorials:
|
|
85
|
+
processes — What is a process and how do they work?
|
|
86
|
+
memory — How does the OS manage memory?
|
|
87
|
+
filesystem — How are files stored and organised?
|
|
88
|
+
shell — What is a shell and why do we need one?
|
|
89
|
+
scheduling — How does the CPU decide what to run next?
|
|
90
|
+
Type 'learn <topic>' to start a tutorial.
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Features
|
|
94
|
+
|
|
95
|
+
- **Six CPU schedulers** -- FCFS, Round Robin, Priority, Aging, MLFQ, and CFS with multi-core support
|
|
96
|
+
- **Virtual memory** -- page tables, address translation, swap (FIFO/LRU/Clock), slab allocator, and mmap
|
|
97
|
+
- **Journaled filesystem** -- inodes, directories, hard/soft links, file descriptors, /proc, and crash recovery
|
|
98
|
+
- **Full network stack** -- sockets, DNS, HTTP, and TCP with three-way handshake, flow control, and congestion control
|
|
99
|
+
- **Shell scripting** -- pipes, variables, conditionals, job control, tab completion, and 80+ built-in commands
|
|
100
|
+
- **Interactive tutorials** -- guided lessons that teach OS concepts hands-on using real system calls
|
|
101
|
+
|
|
102
|
+
## Install
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
pip install pyos-learn
|
|
106
|
+
pyos
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Want the browser-based terminal too?
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
pip install pyos-learn[web]
|
|
113
|
+
pyos-web
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Learn the Concepts
|
|
117
|
+
|
|
118
|
+
Each guide explains one part of the OS with real-world analogies and simple language.
|
|
119
|
+
|
|
120
|
+
| Guide | What You'll Learn |
|
|
121
|
+
|-------|-------------------|
|
|
122
|
+
| [What Is an OS?](docs/concepts/what-is-an-os.md) | The big picture -- what an OS does and why you need one |
|
|
123
|
+
| [Processes](docs/concepts/processes.md) | Programs that are running, how they take turns, forking, and threads |
|
|
124
|
+
| [Memory](docs/concepts/memory.md) | How the OS manages limited memory with pages, virtual addresses, and swap |
|
|
125
|
+
| [Filesystem](docs/concepts/filesystem.md) | How files and folders are organised, and how they're saved to disk |
|
|
126
|
+
| [The Kernel](docs/concepts/kernel-and-syscalls.md) | The brain of the OS -- boot sequence and system calls |
|
|
127
|
+
| [The Shell](docs/concepts/shell.md) | Typing commands, pipes, scripting, and environment variables |
|
|
128
|
+
| [Devices and Networking](docs/concepts/devices-and-networking.md) | Hardware, inter-process communication, disk scheduling, and sockets |
|
|
129
|
+
| [Interrupts and Timers](docs/concepts/interrupts.md) | Interrupt controller, vectors, masking, timer, preemption |
|
|
130
|
+
| [TCP: Reliable Delivery](docs/concepts/tcp.md) | Three-way handshake, flow control, congestion control, retransmission |
|
|
131
|
+
| [Users and Safety](docs/concepts/users-and-safety.md) | Permissions, signals, logging, and deadlocks |
|
|
132
|
+
| [Synchronization](docs/concepts/synchronization.md) | Mutexes, semaphores, condition variables, and race conditions |
|
|
133
|
+
| [The Boot Chain](docs/concepts/bootloader.md) | What happens between pressing power and seeing a prompt |
|
|
134
|
+
| [Framebuffer](docs/concepts/framebuffer.md) | Pixel-level graphics, drawing shapes, and displaying images |
|
|
135
|
+
| [TUI Dashboard](docs/concepts/tui.md) | A live terminal dashboard that shows OS internals in real time |
|
|
136
|
+
| [Permissions](docs/concepts/permissions.md) | File ownership, read/write/execute bits, groups, and ACLs |
|
|
137
|
+
| [Binary Loader](docs/concepts/binary-loader.md) | Loading and running programs -- how `exec` works |
|
|
138
|
+
| [Containers](docs/concepts/containers.md) | Lightweight isolation with PID, mount, and network namespaces |
|
|
139
|
+
| [Inter-Machine Networking](docs/concepts/inter-machine-networking.md) | Connecting multiple kernels with bridges and clusters |
|
|
140
|
+
| [Interactive Tutorials](docs/concepts/tutorials.md) | Guided lessons that teach OS concepts hands-on |
|
|
141
|
+
| [Web UI](docs/concepts/web-ui.md) | Browser-based terminal interface |
|
|
142
|
+
|
|
143
|
+
## Development
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
git clone https://github.com/robcox2910/py-os.git
|
|
147
|
+
cd py-os
|
|
148
|
+
uv sync --all-extras
|
|
149
|
+
uv run pytest
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for coding standards and PR workflow.
|
|
153
|
+
|
|
154
|
+
## Releasing
|
|
155
|
+
|
|
156
|
+
Other projects in the series ([PyStack](https://github.com/robcox2910/pystack)) use a pinned release of this one,
|
|
157
|
+
not whatever is on `main`. To publish a change for them:
|
|
158
|
+
|
|
159
|
+
1. Merge the change to `main`.
|
|
160
|
+
2. Tag it: `git tag -a vX.Y.Z -m vX.Y.Z && git push origin vX.Y.Z`.
|
|
161
|
+
A change to the public API bumps the minor version (`v0.1.0` → `v0.2.0`);
|
|
162
|
+
anything else bumps the patch (`v0.1.0` → `v0.1.1`).
|
|
163
|
+
3. In each project that uses it, edit the tag in `[tool.uv.sources]`, run
|
|
164
|
+
`uv lock --upgrade-package <name>`, and open a pull request so CI checks
|
|
165
|
+
the pair together.
|
|
166
|
+
|
|
167
|
+
<!-- series:start -->
|
|
168
|
+
## Related Projects
|
|
169
|
+
|
|
170
|
+
This project is one of a series that builds real systems "from scratch in Python" to teach how they work. See the [series home](https://robcox2910.github.io/) for the full story.
|
|
171
|
+
|
|
172
|
+
| Project | What it teaches | Repository | Docs |
|
|
173
|
+
| --- | --- | --- | --- |
|
|
174
|
+
| **PyOS** | **Operating systems** | [py-os](https://github.com/robcox2910/py-os) | [Docs](https://robcox2910.github.io/py-os/) |
|
|
175
|
+
| Pebble | Compilers and programming languages | [pebble-lang](https://github.com/robcox2910/pebble-lang) | [Docs](https://robcox2910.github.io/pebble-lang/) |
|
|
176
|
+
| PyDB | Relational databases | [pydb](https://github.com/robcox2910/pydb) | [Docs](https://robcox2910.github.io/pydb/) |
|
|
177
|
+
| PyKV | Key-value stores | [pykv](https://github.com/robcox2910/pykv) | [Docs](https://robcox2910.github.io/pykv/) |
|
|
178
|
+
| PyDocDB | Document databases | [pydoc-db](https://github.com/robcox2910/pydoc-db) | [Docs](https://robcox2910.github.io/pydoc-db/) |
|
|
179
|
+
| PyGraphDB | Graph databases | [pygraphdb](https://github.com/robcox2910/pygraphdb) | [Docs](https://robcox2910.github.io/pygraphdb/) |
|
|
180
|
+
| PyTSDB | Time-series databases | [pytsdb](https://github.com/robcox2910/pytsdb) | [Docs](https://robcox2910.github.io/pytsdb/) |
|
|
181
|
+
| PyVecDB | Vector databases | [pyvecdb](https://github.com/robcox2910/pyvecdb) | [Docs](https://robcox2910.github.io/pyvecdb/) |
|
|
182
|
+
| PyColDB | Column-family databases | [pycoldb](https://github.com/robcox2910/pycoldb) | [Docs](https://robcox2910.github.io/pycoldb/) |
|
|
183
|
+
| PyCrypt | Cryptography | [pycrypt](https://github.com/robcox2910/pycrypt) | [Docs](https://robcox2910.github.io/pycrypt/) |
|
|
184
|
+
| PyNet | Computer networking | [pynet](https://github.com/robcox2910/pynet) | [Docs](https://robcox2910.github.io/pynet/) |
|
|
185
|
+
| PyWeb | HTTP web servers | [pyweb](https://github.com/robcox2910/pyweb) | [Docs](https://robcox2910.github.io/pyweb/) |
|
|
186
|
+
| PyGit | Version control | [pygit](https://github.com/robcox2910/pygit) | [Docs](https://robcox2910.github.io/pygit/) |
|
|
187
|
+
| PySearch | Search engines | [pysearch](https://github.com/robcox2910/pysearch) | [Docs](https://robcox2910.github.io/pysearch/) |
|
|
188
|
+
| PyMQ | Message queues | [pymq](https://github.com/robcox2910/pymq) | [Docs](https://robcox2910.github.io/pymq/) |
|
|
189
|
+
| PyLLM | Language models (the brain) | [pyllm](https://github.com/robcox2910/pyllm) | [Docs](https://robcox2910.github.io/pyllm/) |
|
|
190
|
+
| PyScheduler | Job scheduling | [pyscheduler](https://github.com/robcox2910/pyscheduler) | [Docs](https://robcox2910.github.io/pyscheduler/) |
|
|
191
|
+
| PyStack | Full-stack integration | [pystack](https://github.com/robcox2910/pystack) | [Docs](https://robcox2910.github.io/pystack/) |
|
|
192
|
+
<!-- series:end -->
|
|
193
|
+
|
|
194
|
+
## Links
|
|
195
|
+
|
|
196
|
+
- [Documentation](https://robcox2910.github.io/py-os/)
|
|
197
|
+
- [Shell Reference](docs/shell-reference.md) -- all 80+ commands by category
|
|
198
|
+
- [Architecture](docs/architecture.md) -- technical overview of every module
|
|
199
|
+
- [Visual Guide](docs/diagrams.md) -- architecture diagrams
|
|
200
|
+
|
|
201
|
+
<!-- docs:start -->
|
|
202
|
+
## Documentation
|
|
203
|
+
|
|
204
|
+
Full docs (with kid-friendly explanations of every idea): https://robcox2910.github.io/py-os/
|
|
205
|
+
<!-- docs:end -->
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
py_os/__init__.py,sha256=ISMnoFS4-vc0wuBPW1-JCQ106FlvOZZtqpPlLYjn0LY,84
|
|
2
|
+
py_os/__main__.py,sha256=eKdbA2szDY2jIcUbyGgZ08eYreUA2To5o0V04FBO7cU,88
|
|
3
|
+
py_os/_version.py,sha256=RCY04NY0kBCyn6ttH6lnVL6Gz2gceOrt45f0yDOOU8A,520
|
|
4
|
+
py_os/bootloader.py,sha256=HnpXGPh_kEUuI1kaLekayLDBYMStpGYLCm6dUhET1pg,6800
|
|
5
|
+
py_os/completer.py,sha256=vstLRECoP19gz_7IXd-WCitK_rquqn8Cy6HAiwcKmQ4,8370
|
|
6
|
+
py_os/containers.py,sha256=3gZSSHD8Y9IItkv_JKBFd7EBX0uJi-A2tnFwGhvqTUE,10786
|
|
7
|
+
py_os/env.py,sha256=JfW8-zSz40lqu6Xuypox8XK7atPkLDC5rgjEMld0poM,2243
|
|
8
|
+
py_os/jobs.py,sha256=1fbeea9Y-lcbavwKWjUVAllnE1oYTolvrdWfwF1sLfk,3236
|
|
9
|
+
py_os/kernel.py,sha256=YODPmFEQ8tLzi6GGFPHtwKmEAn-8sZm-4M9-lOg9o-w,128581
|
|
10
|
+
py_os/logging.py,sha256=HRwRBflcQ8d4eoP_FtsXvTGBKvhjEh-sqG9_Deou0Ds,3568
|
|
11
|
+
py_os/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
|
+
py_os/repl.py,sha256=ksn8ZoBX-2fomqE4ZaX58kvt8Vmnk9wKvms8qvtnqow,3584
|
|
13
|
+
py_os/syscalls.py,sha256=DU-CZkc8ex6b2sSV6Of2BEIneAQOAgGxBGRggVeGqnU,83567
|
|
14
|
+
py_os/tutorials.py,sha256=8hbZN2zWsl00x74zG34O-J5ZdZN4wXcI-kMjUFI8lOI,31075
|
|
15
|
+
py_os/users.py,sha256=VDJLlm6JMbNwLJ7BVJb6ivlc0cYnG9tSNebXmkqBk9E,15094
|
|
16
|
+
py_os/fs/__init__.py,sha256=xHFSdwnU-1z9PPKxO3e58UvXC_cd6X0jpUeONePwEVY,1051
|
|
17
|
+
py_os/fs/fd.py,sha256=zaUiFq0_vgyV9TSf5QTvu8Xpsxf30VruF613jYrxL5s,4458
|
|
18
|
+
py_os/fs/filesystem.py,sha256=oL-fPIJQ-6YruLogP-dknbJFrSKbW1VcUeLzAjmpKjs,20138
|
|
19
|
+
py_os/fs/journal.py,sha256=Nic3z508RkFXuaH7qMb5C2hXwxzhOb-mvdgQNQYnVyA,17407
|
|
20
|
+
py_os/fs/persistence.py,sha256=8qJXj0fn-kiSffzBs21eO9ezzDF-gEMosUntmnJRG_0,2727
|
|
21
|
+
py_os/fs/procfs.py,sha256=OpKhV3gLU1NC1AkKJoRT6gGoLBGlykUiJflm8vV3BH0,11878
|
|
22
|
+
py_os/io/__init__.py,sha256=7NF7oOlMiFS7rbKTVNCm1Kn7afv4qa209m0R_iR_Zzo,2087
|
|
23
|
+
py_os/io/bridge.py,sha256=meQKEbz77RONwsX5zwN7rwqji9hExLDNikE4Y8jx0gQ,10609
|
|
24
|
+
py_os/io/devices.py,sha256=eDoAGXxDy9MY4xVcL0j1A-AJ9lxzT0Zhf27azYARujc,5564
|
|
25
|
+
py_os/io/disk.py,sha256=Gl3wiEA5ZCd5jouVV2yCqS7VkRENu1dMuAsTVcQKE6Q,7823
|
|
26
|
+
py_os/io/dns.py,sha256=iInGYV-17AP1WtX1VgfRMl5pJ8kt6CS8laZeeMFKJ0I,3134
|
|
27
|
+
py_os/io/framebuffer.py,sha256=T6TbFfr5POSuJlw5n75pEzAlZTESPgHgOZ3r_TknoyQ,5663
|
|
28
|
+
py_os/io/http.py,sha256=cz3ugp6BiCVlB_I6xxrqoGTKdwJlQmNKobuy96u0-n8,7857
|
|
29
|
+
py_os/io/interrupts.py,sha256=fkp6fygpZYx_YChFsLOxzDn0xoO9MRzKRzIBzdK2DgA,9262
|
|
30
|
+
py_os/io/ipc.py,sha256=EgqIR831tXpehIALTMAdaoFVvCyzvTwDxzcUMRjAZwo,4100
|
|
31
|
+
py_os/io/networking.py,sha256=4gwm6OyC3D7h0wXGkH3SJdC2fuA6aq2C57oW7nUV61o,10391
|
|
32
|
+
py_os/io/shm.py,sha256=uCo2XQZLlIaWAWfEgERNbmrw378c7-_LIx8jJBCroas,1805
|
|
33
|
+
py_os/io/tcp.py,sha256=HN76BhDgP4C7yR1LfUwhBvy7z1L0gnntk38PHdjO7ps,26842
|
|
34
|
+
py_os/io/timer.py,sha256=VpGP_QqabKoryzJGZS40FCmYEU9d4jV2u7f-agkxrAE,4516
|
|
35
|
+
py_os/memory/__init__.py,sha256=lzh8L_MhfevqFWsK_rDelz0PDJiQLL8HUjRpBT6zPmM,892
|
|
36
|
+
py_os/memory/manager.py,sha256=6lP1q1IM6CjQLSwuFNaMNWn-ZFIhkfziAOMHYEeLSVY,7293
|
|
37
|
+
py_os/memory/mmap.py,sha256=HwQy4PO5q8SZrDnq9NyLkHJXNuiRmQlzGrOlU6qyj1s,1638
|
|
38
|
+
py_os/memory/slab.py,sha256=_ruRF9NoWkQm1H7sqm8nev5W5HMdQgfEPoU-wkDF6Qs,14908
|
|
39
|
+
py_os/memory/swap.py,sha256=rwL4Z4UYqvvbSgutfV00zUt4YinHRcjud-SUS5rRgpA,14484
|
|
40
|
+
py_os/memory/virtual.py,sha256=2O5YTx1mDhxkNR2hIBuY6va8ydk_HAPsjUqEIIzNgSA,8504
|
|
41
|
+
py_os/process/__init__.py,sha256=3Q4wA9qFMu7jxbKwibWsfHxufHjBYFIzOtD6yPJI0pc,942
|
|
42
|
+
py_os/process/binary.py,sha256=PljUki3MgmpphNYyaSb_sar_55AIota_05e3hPLF4og,12797
|
|
43
|
+
py_os/process/pcb.py,sha256=64YINo81CBRbG41xAOp_wCDjrsTyBc2GlKye8t4Wdqc,13644
|
|
44
|
+
py_os/process/scheduler.py,sha256=uJ1oieIuH46G9inVUX1MAnCI4I8m7urXwNAIdDCuJq8,28506
|
|
45
|
+
py_os/process/signals.py,sha256=hs6hjKMLkvQu60dxdnwhzwKNq_Anma-86bTevt5UB9M,3291
|
|
46
|
+
py_os/process/threads.py,sha256=xHRDFsokgMqhi7G8wFrIteNAc33hghX4xDt9ikAnY_k,4985
|
|
47
|
+
py_os/shell/__init__.py,sha256=sGqubpCnXqrdxDYIP2k0On30ZSNcl-zX8gsW54w6AEw,2153
|
|
48
|
+
py_os/shell/base.py,sha256=RssovgXKDuJ6l3TyUAz6R6ppdusoQmeJAutTZGyF5aY,21083
|
|
49
|
+
py_os/shell/commands/__init__.py,sha256=LHjz8PQ0HCvvJ0ujEEm_YJfVh5Cg0ZVoW31pK0EsjE8,859
|
|
50
|
+
py_os/shell/commands/basics.py,sha256=yX2a4lLjAKTDyU03CW0N1lxgQ2NNDJgxfWY5G6GNCeQ,3970
|
|
51
|
+
py_os/shell/commands/devices.py,sha256=fehv02H_zPNPwxWeK_verxFU-zkuA3R5Yk7eJcfTIIE,14733
|
|
52
|
+
py_os/shell/commands/files.py,sha256=k2VnKYK0k3dCvmCMv6RVm2jBNH8fzFmIKc3rvDjkY_Y,19192
|
|
53
|
+
py_os/shell/commands/isolation.py,sha256=HmRNArhuYXnayrrkppeQYfMoqC53MSqnQT1rEli5AAI,10590
|
|
54
|
+
py_os/shell/commands/learn.py,sha256=Ur_jM0oa7i2N_r8hFejFyJMzMa1jZX0uUkhzNnPK8Ww,1046
|
|
55
|
+
py_os/shell/commands/memory.py,sha256=Xe7xT8Sn2NQqeZQbC1-yXtZrLrsRRZJ47n13jd-DkKI,18159
|
|
56
|
+
py_os/shell/commands/network.py,sha256=9NV1n8rf5ttyQ2bC7ETFEP0rTdMX9FebNKZbx7h6FP8,30031
|
|
57
|
+
py_os/shell/commands/processes.py,sha256=r_zCF4AXFFCm2On_aF2gNjnA97VgVjojNenhxoF0_b8,42354
|
|
58
|
+
py_os/shell/commands/sync.py,sha256=aePAAG4XC5hXKTCccN8qbpQxZAw0hVRcblwBAy5435M,19561
|
|
59
|
+
py_os/shell/commands/users.py,sha256=YoPSGfeNVP1zelIX8CEE3hn3p_Budw2FLmjIve6jUX4,5282
|
|
60
|
+
py_os/sync/__init__.py,sha256=1lVOCpWesVG7RvLRvqv4RZbN055thFXjzMODltuaswA,780
|
|
61
|
+
py_os/sync/deadlock.py,sha256=7icCHt1CDLodJWVBGY0FMCTgBgD66VRMJDy3BjQH_ko,9487
|
|
62
|
+
py_os/sync/inheritance.py,sha256=FKJmBvYZCFIWvwuL_3-nuD3E2DxUFCcjfUtKBTZfQdo,6867
|
|
63
|
+
py_os/sync/ordering.py,sha256=RXGmLIWLpcqW-cBcO1W4wWeELSZst0oKbxCxjlnCWw4,7388
|
|
64
|
+
py_os/sync/primitives.py,sha256=cWoDThw1ytOVQFmYgSQH7SmoIZMJHMguq9eChTGTKzs,23024
|
|
65
|
+
py_os/tui/__init__.py,sha256=ivIrIDQom5BiWlpqLquwRi2j-UrdnSrutYt2_A7PMzA,206
|
|
66
|
+
py_os/tui/app.py,sha256=hYx6p-XJ60_ldotaR2HN5Yfzr52SRzFZjAq6sEgm0nw,4042
|
|
67
|
+
py_os/tui/widgets.py,sha256=coswN1G27qp766UJ51O3QkH05XMA-rfteNxX9MYtWCY,4628
|
|
68
|
+
py_os/web/__init__.py,sha256=CRf53S1sO59mTgd2X2d-QahHi4wchRE1t3Ry91W0ikk,485
|
|
69
|
+
py_os/web/app.py,sha256=vMpm26gOYuwGoN2kDdLM2hxDDU_ONctOzWIqOsTWS_c,2771
|
|
70
|
+
py_os/web/static/style.css,sha256=QTuER3LAe1jmSfcYqQT3LCrNrBNQpbvvjIKE4Vkwduk,1243
|
|
71
|
+
py_os/web/static/terminal.js,sha256=QuzO54uBYgxGUZF-Ki07EG68cEYBgsquQsL7XZa8k-0,1804
|
|
72
|
+
py_os/web/templates/index.html,sha256=0rhqKLLV70_2PNzD7Ctp8qRH9IMHhYuBTD7grXAXWtY,728
|
|
73
|
+
fromscratch_pyos-0.3.0.dist-info/METADATA,sha256=c0w65vCzLYyGa-7BZysdSbnYdmv1JiPiJ4U1UjAwskQ,10541
|
|
74
|
+
fromscratch_pyos-0.3.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
75
|
+
fromscratch_pyos-0.3.0.dist-info/entry_points.txt,sha256=4zHzRCJ_SMpscOw_jkX1gKNC-F2x9qaUJRO4KcgsyJc,100
|
|
76
|
+
fromscratch_pyos-0.3.0.dist-info/licenses/LICENSE,sha256=NtHM2ak--oE71VCcY50kcCoC1cKS0LRUsxq_xA89RNc,1064
|
|
77
|
+
fromscratch_pyos-0.3.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Rob Cox
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
py_os/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""PyOS - A simulated operating system built in Python for learning OS concepts."""
|
py_os/__main__.py
ADDED
py_os/_version.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# file generated by vcs-versioning
|
|
2
|
+
# don't change, don't track in version control
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"__version__",
|
|
7
|
+
"__version_tuple__",
|
|
8
|
+
"version",
|
|
9
|
+
"version_tuple",
|
|
10
|
+
"__commit_id__",
|
|
11
|
+
"commit_id",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
version: str
|
|
15
|
+
__version__: str
|
|
16
|
+
__version_tuple__: tuple[int | str, ...]
|
|
17
|
+
version_tuple: tuple[int | str, ...]
|
|
18
|
+
commit_id: str | None
|
|
19
|
+
__commit_id__: str | None
|
|
20
|
+
|
|
21
|
+
__version__ = version = '0.3.0'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 3, 0)
|
|
23
|
+
|
|
24
|
+
__commit_id__ = commit_id = None
|
py_os/bootloader.py
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
"""Bootloader — simulated firmware POST and boot chain.
|
|
2
|
+
|
|
3
|
+
Every real computer follows a boot chain before you see a shell prompt:
|
|
4
|
+
|
|
5
|
+
Firmware POST → Bootloader → Kernel → Userspace
|
|
6
|
+
|
|
7
|
+
Think of it like opening a school building each morning:
|
|
8
|
+
|
|
9
|
+
1. **Firmware POST** — Security guard checks lights, water, doors.
|
|
10
|
+
2. **Bootloader** — Janitor fetches "Today's School Plan" from the
|
|
11
|
+
supply closet (disk) and hands it to the principal.
|
|
12
|
+
3. **Kernel boot** — Principal sets up each department from the plan.
|
|
13
|
+
4. **Userspace** — Vice principal opens the front desk (shell) so
|
|
14
|
+
students can check in.
|
|
15
|
+
|
|
16
|
+
This module simulates that chain so you can see what happens between
|
|
17
|
+
pressing the power button and getting a shell prompt.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
import json
|
|
23
|
+
from dataclasses import dataclass, field
|
|
24
|
+
from enum import StrEnum
|
|
25
|
+
from typing import TYPE_CHECKING
|
|
26
|
+
|
|
27
|
+
from py_os.kernel import Kernel
|
|
28
|
+
|
|
29
|
+
if TYPE_CHECKING:
|
|
30
|
+
from pathlib import Path
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class BootStage(StrEnum):
|
|
34
|
+
"""Represent the current phase of the boot chain.
|
|
35
|
+
|
|
36
|
+
The boot process moves through these stages in order:
|
|
37
|
+
FIRMWARE → BOOTLOADER → KERNEL → USERSPACE.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
FIRMWARE = "firmware"
|
|
41
|
+
BOOTLOADER = "bootloader"
|
|
42
|
+
KERNEL = "kernel"
|
|
43
|
+
USERSPACE = "userspace"
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@dataclass(frozen=True)
|
|
47
|
+
class PostResult:
|
|
48
|
+
"""Capture the outcome of the firmware Power-On Self-Test (POST).
|
|
49
|
+
|
|
50
|
+
POST checks that essential hardware works before the OS loads.
|
|
51
|
+
If any check fails, the machine cannot boot safely.
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
memory_ok: bool
|
|
55
|
+
disk_ok: bool
|
|
56
|
+
devices_ok: bool
|
|
57
|
+
messages: tuple[str, ...] = ()
|
|
58
|
+
|
|
59
|
+
@property
|
|
60
|
+
def passed(self) -> bool:
|
|
61
|
+
"""Return True only if every hardware check passed."""
|
|
62
|
+
return self.memory_ok and self.disk_ok and self.devices_ok
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@dataclass(frozen=True)
|
|
66
|
+
class KernelImage:
|
|
67
|
+
"""Represent the kernel binary stored on disk.
|
|
68
|
+
|
|
69
|
+
In a real system the bootloader reads the kernel image from a
|
|
70
|
+
partition (e.g. ``/boot/vmlinuz``). Our image carries the
|
|
71
|
+
configuration the kernel needs to initialise itself.
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
version: str
|
|
75
|
+
total_frames: int
|
|
76
|
+
default_policy: str
|
|
77
|
+
boot_args: dict[str, str] = field(default_factory=lambda: {}) # noqa: PIE807
|
|
78
|
+
num_cpus: int = 1
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class BootError(RuntimeError):
|
|
82
|
+
"""Raise when the boot chain cannot continue.
|
|
83
|
+
|
|
84
|
+
Examples: POST failure, missing kernel image, corrupt image file.
|
|
85
|
+
"""
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class Bootloader:
|
|
89
|
+
"""Simulate the firmware + bootloader that starts the kernel.
|
|
90
|
+
|
|
91
|
+
Usage::
|
|
92
|
+
|
|
93
|
+
bootloader = Bootloader()
|
|
94
|
+
kernel = bootloader.boot() # full chain, returns running kernel
|
|
95
|
+
|
|
96
|
+
"""
|
|
97
|
+
|
|
98
|
+
def __init__(
|
|
99
|
+
self,
|
|
100
|
+
*,
|
|
101
|
+
kernel_image_path: Path | None = None,
|
|
102
|
+
total_frames: int = 64,
|
|
103
|
+
num_cpus: int = 1,
|
|
104
|
+
) -> None:
|
|
105
|
+
"""Create a bootloader with optional kernel image path.
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
kernel_image_path: Path to a JSON kernel image file.
|
|
109
|
+
If None, a default image is constructed in memory.
|
|
110
|
+
total_frames: Default memory frame count (used when no
|
|
111
|
+
image file is provided).
|
|
112
|
+
num_cpus: Number of CPUs to simulate (default 1).
|
|
113
|
+
|
|
114
|
+
"""
|
|
115
|
+
self._kernel_image_path = kernel_image_path
|
|
116
|
+
self._total_frames = total_frames
|
|
117
|
+
self._num_cpus = num_cpus
|
|
118
|
+
self._stage: BootStage = BootStage.FIRMWARE
|
|
119
|
+
self._boot_log: list[str] = []
|
|
120
|
+
self._kernel: Kernel | None = None
|
|
121
|
+
|
|
122
|
+
@property
|
|
123
|
+
def stage(self) -> BootStage:
|
|
124
|
+
"""Return the current boot stage."""
|
|
125
|
+
return self._stage
|
|
126
|
+
|
|
127
|
+
@property
|
|
128
|
+
def boot_log(self) -> list[str]:
|
|
129
|
+
"""Return the accumulated boot log messages."""
|
|
130
|
+
return list(self._boot_log)
|
|
131
|
+
|
|
132
|
+
@property
|
|
133
|
+
def kernel(self) -> Kernel | None:
|
|
134
|
+
"""Return the booted kernel, or None if boot has not completed."""
|
|
135
|
+
return self._kernel
|
|
136
|
+
|
|
137
|
+
def boot(self) -> Kernel:
|
|
138
|
+
"""Run the full boot chain and return a running kernel.
|
|
139
|
+
|
|
140
|
+
Raises:
|
|
141
|
+
BootError: If POST fails or the kernel image is missing.
|
|
142
|
+
|
|
143
|
+
"""
|
|
144
|
+
# Stage 1: Firmware POST
|
|
145
|
+
self._stage = BootStage.FIRMWARE
|
|
146
|
+
post_result = self._run_post()
|
|
147
|
+
if not post_result.passed:
|
|
148
|
+
msg = "POST failed: " + ", ".join(post_result.messages)
|
|
149
|
+
raise BootError(msg)
|
|
150
|
+
self._boot_log.extend(f"[POST] {m}" for m in post_result.messages)
|
|
151
|
+
|
|
152
|
+
# Stage 2: Load kernel image
|
|
153
|
+
self._stage = BootStage.BOOTLOADER
|
|
154
|
+
image = self._load_kernel_image()
|
|
155
|
+
self._boot_log.append(f"[BOOT] Loading kernel image v{image.version} ... OK")
|
|
156
|
+
|
|
157
|
+
# Stage 3: Boot kernel
|
|
158
|
+
self._stage = BootStage.KERNEL
|
|
159
|
+
kernel = Kernel(total_frames=image.total_frames, num_cpus=image.num_cpus)
|
|
160
|
+
kernel.boot()
|
|
161
|
+
self._kernel = kernel
|
|
162
|
+
|
|
163
|
+
# Stage 4: Userspace ready
|
|
164
|
+
self._stage = BootStage.USERSPACE
|
|
165
|
+
return kernel
|
|
166
|
+
|
|
167
|
+
def _run_post(self) -> PostResult:
|
|
168
|
+
"""Simulate the Power-On Self-Test.
|
|
169
|
+
|
|
170
|
+
Check memory frames, disk accessibility, and device availability.
|
|
171
|
+
"""
|
|
172
|
+
messages: list[str] = []
|
|
173
|
+
memory_ok = self._total_frames > 0
|
|
174
|
+
messages.append(
|
|
175
|
+
f"Memory: {self._total_frames} frames ... " + ("OK" if memory_ok else "FAIL")
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
# Disk is always accessible in our simulation
|
|
179
|
+
disk_ok = True
|
|
180
|
+
messages.append("Disk: accessible ... OK")
|
|
181
|
+
|
|
182
|
+
# Devices are always available in our simulation
|
|
183
|
+
devices_ok = True
|
|
184
|
+
messages.append("Devices: ready ... OK")
|
|
185
|
+
|
|
186
|
+
return PostResult(
|
|
187
|
+
memory_ok=memory_ok,
|
|
188
|
+
disk_ok=disk_ok,
|
|
189
|
+
devices_ok=devices_ok,
|
|
190
|
+
messages=tuple(messages),
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
def _load_kernel_image(self) -> KernelImage:
|
|
194
|
+
"""Load the kernel image from a JSON file or construct defaults.
|
|
195
|
+
|
|
196
|
+
Raises:
|
|
197
|
+
BootError: If the image file is specified but cannot be read.
|
|
198
|
+
|
|
199
|
+
"""
|
|
200
|
+
if self._kernel_image_path is not None:
|
|
201
|
+
try:
|
|
202
|
+
data = json.loads(self._kernel_image_path.read_text())
|
|
203
|
+
return KernelImage(
|
|
204
|
+
version=data.get("version", "0.1.0"),
|
|
205
|
+
total_frames=data.get("total_frames", self._total_frames),
|
|
206
|
+
default_policy=data.get("default_policy", "fcfs"),
|
|
207
|
+
boot_args=data.get("boot_args", {}),
|
|
208
|
+
num_cpus=data.get("num_cpus", self._num_cpus),
|
|
209
|
+
)
|
|
210
|
+
except (OSError, json.JSONDecodeError) as e:
|
|
211
|
+
msg = f"Cannot load kernel image: {e}"
|
|
212
|
+
raise BootError(msg) from e
|
|
213
|
+
|
|
214
|
+
return KernelImage(
|
|
215
|
+
version="0.1.0",
|
|
216
|
+
total_frames=self._total_frames,
|
|
217
|
+
default_policy="fcfs",
|
|
218
|
+
num_cpus=self._num_cpus,
|
|
219
|
+
)
|