-
-
Notifications
You must be signed in to change notification settings - Fork 5
Filesystem
A POSIX-like VFS over four backends: a ramdisk loaded from the initramfs, a read/write EXT2 disk mounted at /mnt, the generated /proc pseudo-filesystem, and /dev special files. All four are reached through the same open/read/write/getdents calls — there are no side-channel syscalls.
See also: Architecture, Drivers, Syscalls, Shell, GUI Subsystem
One unified namespace over a pool of 256 nodes (MAX_INODES), plus a free-list for the transient nodes that back mounted files. Paths resolve relative to the calling process's working directory, with . and .. normalised.
| Function | Purpose |
|---|---|
vfs_open / read / write / close
|
File I/O |
vfs_pread / vfs_pwrite
|
Offset-aware I/O — the per-fd offset tracker and mmap use these |
vfs_readdir |
Directory listing across ramdisk, EXT2 and /proc
|
vfs_mkdir / vfs_unlink / vfs_rename
|
Namespace mutation |
vfs_chdir / vfs_getcwd
|
Navigation; returns a full absolute path |
vfs_isdir |
Directory test |
vfs_mount / vfs_find_mount
|
The 16-entry mount table |
Working directories are per-process. Each process carries its own cwd, inherited across fork and kept across execve. Each GUI terminal window tracks its own; the kernel shell keeps a single global one.
The node pool, the free-list and the mount table each sit behind a spinlock, and the EXT2 driver has one of its own. This is not theoretical: the EXT2 driver uses a single global scratch buffer for the duration of an operation, so two cores inside it at once would corrupt each other's block reads.
One subtlety if you work on this code: a VFS fd is a node pointer, so the pool must track who holds one — a node cannot be recycled while an fd still names it.
The default filesystem, built at boot from the initramfs:
/
├── bin/ etc/ mnt/ proc/ root/ tmp/ usr/ var/
├── dev/ null zero random urandom
├── home/
│ └── <user>/ created at first login, seeded with starter content
└── *.elf the userspace programs
A CPIO newc archive (magic 070701) embedded in the kernel as a C byte array in initramfs_data.h, generated by tools/mkinitramfs.py. At boot it is unpacked into the ramdisk in one pass. See Building for how to regenerate it.
Real VFS nodes carrying a dev_type field. vfs_pread/vfs_pwrite intercept on that field, so no new syscalls were needed and ordinary tools work unchanged — ls /dev, cat, and shell redirection all behave.
| Node | Read | Write |
|---|---|---|
/dev/null |
EOF (0 bytes) | Discarded |
/dev/zero |
Endless null bytes | Discarded |
/dev/random |
Pseudo-random bytes from a lazily-seeded xorshift64 PRNG | Discarded |
/dev/urandom |
Alias of /dev/random
|
Discarded |
These are not the kernel's cryptographic RNG. TLS and ephemeral key generation use
csprng_bytes()— HMAC_DRBG-SHA256 seeded from RDSEED/RDRAND. See Cryptography and TLS.
Generated nodes whose contents are synthesized on read by proc_generate() — nothing is stored. proc_sync() reconciles the per-pid directories with the live process table and is called from vfs_open and vfs_isdir, so cat /proc/<pid>/status always sees a current view.
| Path | Contents |
|---|---|
/proc/version |
Kernel banner |
/proc/meminfo |
MemTotal / MemUsed / MemFree
|
/proc/uptime |
tick_count converted to seconds |
/proc/cpuinfo |
CPU identification |
| Path | Contents |
|---|---|
/proc/<pid>/status |
Name, Pid, PPid, State
|
/proc/<pid>/cmdline |
Full command line including argv |
/proc/<pid>/maps |
Mapped memory regions with their address ranges |
Process names are real, set by proc_set_comm() — a process shows as init, not elf.
Two ring-3 tools read nothing but these files: free (from /proc/meminfo) and pmap [pid] (from /proc/<pid>/maps).
A read/write EXT2 driver over ATA PIO, auto-mounted at /mnt when a disk is present.
- Superblock, block groups, inode tables, directory entries
- Inode and block allocation, directory creation, file writes, unlink
- Fd-based file I/O flushed to disk on close — persistent across reboots
- Fd-based
readdir, so the GUI file manager can browse and edit the disk - A write-through sector cache — it accelerates reads and cannot corrupt the disk, because every write still reaches the platter
The write path is verified against e2fsck, not against itself. That distinction matters: a driver that reads back what it wrote can be self-consistently wrong.
df reports usage of the mounted filesystem.
vfs_open detects a path under a mount point via vfs_find_mount and returns a transient mount-backed node preloaded from the filesystem. vfs_write/vfs_pwrite flush the whole node back; vfs_close frees it. Opening a directory probes readdir — the EXT2 driver returns −1 for non-directories — and loads every entry once, which vfs_readdir then serves by index. The node free-list exists precisely so these per-open nodes do not exhaust the pool.
The EXT2 image (ext2-test.img under QEMU) holds:
| Path (as seen from NyxOS) | Purpose |
|---|---|
/etc/passwd |
User accounts — see Security |
/mnt/doom1.wad |
The DOOM shareware WAD |
anything you write under /mnt
|
Persists across reboots |
Kernel shell: ls cd pwd cat touch mkdir rm cp mv write head tail grep sort wc find tree diff df mount open
Ring 3: ls cat touch mkdir rm cp mv head tail grep sort find wc stat less more edit
See Shell for the full reference.
-
Kernel Data Structures -
vfs_node_tfield by field - Drivers - the ATA driver EXT2 sits on
- Syscalls - the file I/O interface
- Userspace - the coreutils that use it
- The Second Extended File System - Dave Poirier
- cpio newc format - Linux kernel documentation
NyxOS v6.4.363 · GPL v2 · GitHub · uselessalter on Discord · nyxos@inbox.lv
NyxOS Wiki
Getting started
Kernel
Storage & network
Graphics & apps
Userspace
HOWTO
- HOWTO-Add-a-system-call
- HOWTO-Write-a-userspace-program
- HOWTO-Add-a-shell-command
- HOWTO-Add-a-GUI-application
Reference
- Syscall-Reference
- Command-Reference
- Hardware-Reference
- Format-Reference
- Kernel-Data-Structures
- Source-Tree-Reference
Project