I'm increasingly tempted to try my hand at making a toy OS - or at least a kernel. There's a few things I desperately want an operating system to do:
1. Have either database-like transactions or (at a minimum) write barriers for file operations. The current filesystem semantics are terrible for databases and other applications which need to not corrupt their data after a crash. fsync() is too heavy, because you can't issue subsequent writes while waiting for fsync. Write barriers have better ergonomics (so, less complex, less buggy database implementations). And they're finer grained - so databases can also run much faster. Seriously, I could rant for hours about this. It drives me nuts.
2. Use event queue like semantics for subscriptions. There's dozens of OS APIs in which the OS exposes some data to applications where the data changes over time. Eg, filesystem watching, USB device insertion/removal, Bluetooth, watching a network device, or a socket, or APIs for htop to see the set of active processes. Each of these APIs has an entirely bespoke - and oftentimes idiosyncratic - API to get changes to that data over time. Sometimes you need to poll and parse a file in procfs. Sometimes there's syscall based APIs. And some of the subscription APIs are just broken sometimes, and they'll fail to notify you about changes sometimes.
I want to try replacing all of that with a simple, unified API which lets you say "tell me the state of <kernel resource X> and tell me when it changes". The kernel then replies with the object's current state and I get messages notifying my application about changes. We should be able to use the same API for every type of kernel object.
It would also be interesting to try making all userspace programs be wasm bundles and run them in ring0. But I suspect that will run slower on modern hardware compared to using native binaries and context switching. ... Maybe. It might depend on the application.
I think this stuff could be done in linux. Event queue style subscriptions would work especially well with io_uring. But I'm kind of excited by the idea of just noodling myself and seeing where I end up. Making stuff is fun.
> I want to try replacing all of that with a simple, unified API which lets you say "tell me the state of <kernel resource X> and tell me when it changes".
Fuchsia's "Signals" are designed in that direction. You get a "handle" to a resource, and the resource has a 32-bit integer with signal bits that you could subscribe to.
The meaning of each bit is different for each type of resource.
(In general operating system terminology, "Signal" means just a message without any payload that would have required any memory allocation. There are many ways to do it, not just the Unix way. Message ports and other abstractions are sometimes built on top of types of signals)
> In general operating system terminology, "Signal" means just a message without any payload that would have required any memory allocation.
Do you have a link for this? It's the first time I'm seeing signals described in terms of lack of memory allocation. I always thought the word "signal" basically meant user-mode interrupts - asynchronously hijacking a thread.
> Have either database-like transactions or (at a minimum) write barriers for file operations.
Go one step further and have the kernel expose a much more structured view of storage to user space by default. 99.9% of user space programs I've written don't want to deal with file IO, they want a database, or some other way for arbitrary in memory objects to be persisted and shared between processes. There's so much room to improve on the 1970s era IO primitives we use by default.
Ironically my understanding is that several operating systems around that time did do that, then Unix came and said "a file is just a bag of bytes in a hierarchical namespace" and we've seemingly never reconsidered
I can imagine that there's a major lack of flexibility inherent in a record-based filesystem. Nowadays we have file formats that introduce a record format on top of the "bag of bytes" for when you want records, but you aren't required to have records of any particular shape and size (or have any records at all) if they don't work for your needs.
Notable major player here was IBM on the AS/400, you had libraries containing objects of various types (such as PGM/Program, FILE/'file', *DTAQ/Data Queue, etc).
'file' objects were effectively database tables, and even things like source code for programs were stored as such.
Eventually IBM added the IFS (integrated file system) to provide a more traditional POSIX-adjacent filesystem that was in fact just a bunch of bits, and it feels weird and out of place with the rest of the system as a result.
One problem with 2. is that subscribing to changes isn't always good enough, since if you go to act on the changes things may update out from under you regardless. Like, if you react to filesystem events, if a new file is created you might have it get deleted before you even register that it was added and do whatever you wanted with it.
I feel like it should be possible to say "I want to reserve access to this resource when something important happens on it". Or just "I want to reserve access to this resource". Hopefully eliminates TOCTOU races. I guess then there have to be different modes to balance scalability/flexibility.
When people complain about antivirus and endpoint security applications slowing their computer down, this is what they're talking about. This leads to user-visible delays (which, to them, seem to be random) as the reserver does what it wants right after the user has done something to the file. Many (most? ALL?) apparent Explorer stalls are really Windows Defender locking and scanning the file right after you did something to it.
It should be possibly to speculatively execute code that's accessing resources and only allowing transactions on system resources to commit successfully if other transactions haven't invalidated them.
Meaning a process could start loading and reading while queuing writes and only writes would block while another process is locking access to the executable to scan it. If the scan succeeds the writes are committed and if it fails it could revoke execution privileges and all the work is undone.
Lot of hand waving there, but when you're not committed to existing file system semantics there is a lot of room for innovation.
Yeah good point. I don't want write stalls because of subscription requests. For things like filesystem watching (for compilers), it'd be enough to have a form of snapshot checkpointing. (There were these FS events within 10ms [..]) / (Then the file contents was XXX) / ... (Then there were these FS events) / and so on.
Its possible you'd end up in situations where the OS would need to retain old file contents if there's both a pending read from a subscriber and subsequent writes. But in most cases, this is fine.
Going back to my original comment, this is the sort of reason I'd like to try this in my own OS kernel rather than try and solve all these problems immediately in linux. It'll give me a chance to try out a few different solutions and see if I can find something that works well.
You can definitely do that, it just means that userspace can now stall access to things unless you're very careful :) Like, one model (often used by EDR, which is why everyone hates them) is that every operation must be "authorized" so it doesn't go through until some evaluation happens. But this means the kernel has to ask a program for every operation, which is slow.
> It would also be interesting to try making all userspace programs be wasm bundles and run them in ring0. But I suspect that will run slower on modern hardware compared to using native binaries and context switching.
If you have all of your programs reside in the same virtual memory space (which is the implication with running them in ring 0), then you get a unique performance advantage in that you don't have to invalidate the TLB. I have no idea how much the amortized performance impact of virtual memory is, unfortunately, so the gains might be trivial, but who knows.
Yeah - if you run things in the kernel you don't need to do TLB flushes or context switches - which can be very expensive. But thats all offset by the fact that wasm code runs slower inherently, because it needs to bounds checks everywhere.
I suspect that programs which make a lot of kernel calls would run faster in the kernel in wasm, and programs that are more compute / memory bound will run faster as native processes. It'd be fun to play around and find where the tradeoffs lie for different applications.
Sorry for being daft, but doesn't this imply that TLB is now shared between all processes? Which means that the cost of flushing the TLB is amortized across context switches? Processes are gonna evict TLB entries from other processes at unpredictable intervals.
If all programs run in ring 0, you can just run them all in the same virtual memory space. Then you don’t need TLB flushes at all. Of course, one bad program could bring the whole system down but that’s the price you pay.
But if programs were written in wasm, that problem goes away. Wasm prevents bad memory accesses by doing memory protection in software. (Every array or pointer access is bounds checked).
> I'm increasingly tempted to try my hand at making a toy OS - or at least a kernel.
I strongly encourage you to do this!
I think writing your own OS is one of the things every dev should do at least once, just for the educational value. The others are writing a game and writing a compiler and linker.
Some of the issues can be improved "hackily" by for instance giving a database software exclusive access to two discrete disks - one for the db file, one for the journal.
Why is this "hacky"? I've long wondered why databases need to be on filesystems, other than simply convenience. If you think about it, a filesystem is, itself, basically a database (not a relational one of course). So it seems like you could improve performance a lot by eliminating the filesystem layer and going straight to direct disk access.
Also, how this would be done would probably change depending on whether you're using a spinning-rust HD or an SSD, or a RAID array.
>I've long wondered why databases need to be on filesystems, other than simply convenience. [...]So it seems like you could improve performance a lot by eliminating the filesystem layer and going straight to direct disk access.
Both Oracle RDBMS and older versions of Microsoft SQL Server had the option to use "raw disk devices" / "raw partitions" instead of the filesystem. It had some obvious justifications such as avoiding the "wasteful double buffering" of the file system cache being redundant to the database's cache and avoiding "unnecessary" extra i/o abstraction layers.
Microsoft later got rid of that option because it wasn't worth the tradeoff of a small performance gain while losing the easier management aspects of NTFS file system.
SQLite essentially achieves this as well by keeping the entire database in one file. It’s even faster than the filesystem in some cases: https://www.sqlite.org/fasterthanfs.html
I'd like to go the other way, and have a filesystem that leverages a proper database for its metadata.
I can search millions of records in a split second in SQL. But searching records on my hard disk takes enormously more time. The solutions out there for speeding it up (like Windows Indexing service) rely on asynchronous indexing that's patched on top of the filesystem instead of integrated realtime within it, and are subsequently brittle (in my experience), slow down your computer at inconvenient times, and too often aren't instantly up date.
Being able to have stored procedures execute when changes trigger would be another interesting aspect that could take the place of event filters and file watchers (especially if critical portions could be configured to happen sequentially & atomically, akin to IRQ handlers).
I feel like databases have gotten lots of love over the decades and are super optimized (and by this point are pretty dang reliable). Filesystems feel like they lost their time in the spotlight and have floundered with less innovation.
Hardware that calculates CRC's of blocks in realtime would also be awesome (imagine what it would do for sync). The ironic thing is your HDD already does this, there's just no way to tap into that information at the software / filesystem driver level.
>I'd like to go the other way, and have a filesystem that leverages a proper database for its metadata.
Microsoft made an attempt back in 2003 at creating a "smarter" file system with rich metadata based on a real database engine (MS SQL Server) ... but eventually abandoned the project: https://en.wikipedia.org/wiki/WinFS
WinFS wasn't necessarily going to completely replace NTFS but Microsoft did have ambitious plans for its integration into everything.
It's interesting that other platforms like Unix/Linux/Apple that were designing "next generation" file systems like ZFS/ext4/APFS after the failed WinFS project had a chance to try adding their own WinFS smart metadata features to but they didn't.
The later fragmentation of user data being spread around in the cloud such as AWS objects, Apple iCloud, Backblaze backups, etc instead of every file saved on home computers makes a "universal rich metadata index stored in a database engine" to be a cross-platform standard by all operating systems less realistic today than back in 2003. Therefore, the core os file systems remain a "dumb blob of bytes" with a separate layer of metadata index db in vendor-specific schemes like Apple Spotlight db, Windows Search in ".edb" file, etc.
When WinFS was canceled, I started my own pet project to build a new kind of file system that totally changed the way file metadata was stored and managed. I built an object based system that could easily handle hundreds of millions of files within a single container (what I called a pod) and do searches much like how you would search a large database table.
The 'file table' contains a 64 byte record for each object and has some very unique characteristics that make searches incredibly fast (e.g. it can find all the photos in under a second, even if there are 20 million of them among 200 million files). You can also attach various metadata 'tags' to each object and find matching objects based on them.
The project is in open beta and anyone can download it and try it out on their own computer.
Yeah they totally missed the mark with WinFS, in my opinion. It was too exotic/foreign with no clear adoption path.
All I want is dumb files with something like SQLite replacing or augmenting the allocation table. Then sprinkle on some new capabilities incrementally.
The reason indexing services don't work synchronously is because it would cause file IO to get far slower than apps expect, and that can break user interfaces and cause unexpected slow downs. There's also no real reason for it to be synchronous in most cases.
Lots - maybe most - applications need to essentially run their own mini database to store user data. I obviously don't want a partition per application, or per word document.
Abstracting away your hard disk is literally the job of your filesystem.
I don't mean that some little SQLite DB for your web browser's storage and settings needs its own partition; that's obviously going too far. I mean for really huge databases, where an entire server is dedicated to running that DB and it has high performance needs.
Fair enough. But I am including all of those little databases.
I agree with you - you could hack around this for a big database by putting it on a dedicated partition (even though you shouldn't need to). But I'm also thinking about applications with little databases that need to live inside the filesystem. They shouldn't need to embed sqlite in order to survive a crash.
A different syscall API would allow you to write a small, fast, efficient database engines (like redis or mysql) without needing all of the complex, performance gobbling tricks that these databases currently have.
A better filesystem API would help databases everywhere.
last time I looked at this, and it was a long time ago, it was around 10% and workload dependent.
if you make direct and locking more robust, and allowed an application to turn off the kernel cache, you would only really need to interact with the filesystem after open in order to change your extents.
+1. this is clearly a place where we can have nice things and performance
For server applications, the trends of virtualization and microservices mean that having "machine" dedicated to running a single application is a very common scenario, and also for server VMs running a bunch of apps it is not obvious that having a partition per application is an issue, it would be trivial for the VM initialization scripts to automagically configure a dedicated partition for each DB.
Having a OS+filesystem running a virtual OS+filesystem running a database has all kinds of redundant caching, and we could systematically skip a layer here.
You probably won't supplant Linux with your toy OS for your own research, but for a software engineer, writing a OS is the closest thing we have to the exhilarating feeling of seeing your code affect real hardware. You haven't lived until a bug of your own causes a triple-fault exception that causes a literal system shutdown.
I started this career writing my own tiny OS in my teens (https://github.com/1player/klesh) and for 20 years I've been wanting to go back, with all the experience I have accumulated.
Just don't make it another UNIX, please. We have enough of those already ;)
> You haven't lived until a bug of your own causes a triple-fault exception that causes a literal system shutdown.
On the OS I work on, I deliberately added a triple fault trigger as a fallback method of rebooting the system if the "normal" methods fail, which I have seen before.
To anyone looking to play with writing their own OS, definitely just do it. It's a lot of fun, and there's almost no limit to how much you can learn. With QEMU and bochs, and VirtualBox, etc... it's not that hard getting started. If you want to play around without starting from scratch, but find Linux source too complicated, give OpenBSD a look. Not that Linux is that hard, but it takes some getting used to how they do things. I find OpenBSD considerably more approachable.
> Just don't make it another UNIX, please. We have enough of those already ;)
Hah thanks for the encouragement! Don't worry, there's no danger on that front. I'm pretty thoroughly bored of the "everything is a file" motif.
I do like unix's idea of making large programs out of small programs that can be composed together. But unix's raw byte streams make a terrible messaging bus.
You're on the right path! My area of interest is actually making messaging (a-la-Smalltalk/Erlang) the root idea everything is built upon, rather than the file stream. The file metaphor made sense in the 1960, not in an ultra-networked world of heterogeneous CPUs. IMO, communication should be the basis of computing.
Which also means inventing a language to build this novel paradigm. As Dan Ingalls said, an operating system is everything that doesn't fit in a language.
I am looking forward to finding the time for this long and quixotic quest :-)
My crazy hobby OS vision of boot to Erlang. I've been working on this for a couple years now, recently made it public as part of a PR to v86 [1] (which is amazing, by the way). 32-bit x86, has drivers for virtio and rtl-8168 (but not ne2k, so no networking in v86, sadly), works with SMP. Probably not better than running beam as init with a FreeBSD kernel, but was more fun?
Thanks! And good idea. The ideal time would have been early 2023, because things have drifted into bitrot a little already. I'll tidy up and see about showing it off hopefully in the next few days.
> The current filesystem semantics are terrible for databases
There was at least one Unix startup (IIRC it was Tolerant Systems) in mid 80s that applied transactional semantics to filesystem operations. I did some contract work for them and found the performance was absolutely abysmal and the system had some deadlocks. Now may be their implementation was not great but I suspect the converse is also true: database semantics are terrible for filesystems :-)
There was at least one database from the mid 80s with abysmal performance and deadlocks too. But plenty of modern databases are fast and correct. The fact this one startup 40 years ago didn’t solve the problem doesn’t say a lot about whether I’ll be able to. Honestly the fact there are some dead bodies on the mountain makes it more fun to give it a go and see how I do.
To be frank, judging by the code I’ve seen over the years, most engineers don’t have a lot of experience or skill at making software run fast.
I'm not sure you mean by soft updates but - kqueue is really just a messaging queue. I want a data subscription system, so I can get a kernel object and get a stream of updates which can be applied to the snapshot in sequence.
kqueue is very limited in terms of what you can subscribe to, and things like filesystem watching usually requires subsequent filesystem calls to see whats actually changed. And that in turn introduces race conditions if the data is changed again before your fs syscalls make it through.
I think there are cleaner APIs out there. I'd like to see if I can find one.
Serenity is one of the only recent OS projects that I think has any potential. It's a very high velocity, high quality project and I think that's down to the community culture Andreas has fostered. They aren't a load of fuddy-duddies who insist on using mailing lists and IRC. Nobody wants to collaborate with a load of grumpy greybeards.
You think a throw back Win 95 clones with UNIX-like internals is what modern users want?
We’ve moved on from “back in my day, the 80s…” computer UI nostalgia to 90s it seems.
10 more years we’ll have Mac OSX Snow Leopard clone project get abandoned (have had a lot of young Millennials and older GenZ hackers talk it up at me as peak computing)
Just because they’re not grumpy doesn’t mean they aren’t nostalgia driven iconoclasts making serenity out of disdain for status quo
You're more than free to do with your own time what you wish. These projects aren't harming you in any way. Who cares what enthusiasts want to do for fun? They're not trying to supplant the OS on your desktop. They're learning something and having fun doing it. I love these sorts of projects.
In contrast, many of us treat computers as a magic black box. The abstraction is great for productively building web apps. But, we've lost sight of how things work and I think that's led to steep decline in performance and, perhaps, security. I don't pine for manual resource management in all things, but knowing how syscalls work can help build context on when and why you should use them. Revisiting how to build an OS that isn't rooted in decades-old Linux or BSD code could be really instructive.
My concern is more so that this project will burn up real resources and be abandoned.
You’re highlighting how subjective things can be and I don’t disagree.
What isn’t subjective is the generations of the 1900s are the first to leave behind an existential threat driven by wasteful economic choices and they seem to be indifferent to doing so just to have fun.
Myself and lot of other software engineers I have worked with feel our jobs are meaningless; the future won’t care about these technologies. They’re hardly regenerative medicine or something so life changing daily life itself is improved forever like indoor plumbing and electricity.
But we feel captured by nostalgia for this work and form of economics, and apathy for a whole
lot of people who will be dead before climate change is real problem
Some people grow gardens. Some rebuild cars. Others 3D print things. Others yet enjoy woodworking. One the grand features of our current society is you're not working 14 hour days, seven days a week in a factory. Without a doubt, there are those working multiple jobs and still struggling to make ends meet. But, fortunately, many are able to work a single job and live a relatively comfortable life. Those that can often have hobbies. It helps them unwind and maybe even enjoy life a little since otherwise so much of it is spent working or sleeping. It's downtime and largely considered positive for mental health and, consequently, one's ability to contribute to society.
Most people aren't solving deep societal needs in their free time. If you want to limit it to software, most of us have jobs that hardly improve society or the planet. Most open source code isn't advancing society. What I don't understand is why you've singled out the participants of this particular project for your ire.
I don't know any of the individuals involved personally. My guess is they're not the ones that built physical products with PFCs, ran coal-powered factories and operated strip mining operations, designed nuclear weaponry, or even fly personal jets. I'd hazard to say your average front-end developer chugging through batteries with inefficient frameworks is doing more harm than this project.
If your aim is to clean up the tech industry, I think that's laudable. I believe tech people have for the most part shirked their own contribution to our carbon footprint or other societal needs. But, I think you'll find there are much bigger targets actively doing harm (or certainly not helping things) regularly because it's profitable and/or convenient.
We haven't improved much since Win 95 in terms of desktop OS UI/UX. Could you remember any substantial UI improvements between Win 95 and Win 11? Local search, improved UAC and a shitload of ads.
> Could you remember any substantial UI improvements between Win 95 and Win 11
Yes I can. Most OSes these days have a OS level fuzzy searching functionality.
This has been my preferred way of launching applications on Windows (Win key), Linux (Win key) and MacOS (CMD+Spc).
I press a hotkey, type the first few characters of the program I'm trying to go to, and press enter. This is also common in text editors and even some web apps. Improves the UX of discovering commands, as compared to endlessly nested menus like the 90s.
There's loads of other things that have improved but this one is just so basic that I couldn't live without it.
Let's not live with rose tinted glasses. Yes, there's backsliding in terms of UX but don't ignore the improvements.
I'm not living with rose tinted glasses, I mentioned search and UAC in my original message. This is not enough to warrant criticism of Win 95 clones. I bet you could add search to Serenity without changing the look and it would still be called a Win 95 clone.
I also tend to use Win key search for launching programs. I would be interested to see if an OS could focus that use case as a primary means of UI. If it did become central to usage, I’d love to see a commonality emerge across terminal centric and GUI OS styles.
It's gone downhill. Scrollbars that only appear half the times you need them, buttons that aren't buttons, not-buttons that are in fact buttons, instead of curated menus Evince has three places you can click and hope to find the function you want in one of them, it's just a mess.
Win 95 had the basic UX down, and Tiger made it look very pretty, but it didn't need any more fixing.
Windows 95 brought us those god-awful cascading menus that would disappear the second you missed a hover target by a single pixel. I for one am glad those died out.
I don't understand how anyone could say that mess was good.
I think this is due to the operating system being replaced by a combination of (1) the web browser; and (2) Steam. Nobody cares what the OS itself is doing, because they aren't using it.
2. Font rendering, hinting, anti-aliasing and subpixel rendering. Together with high-resolution screens for more people.
3. Better multi-threading for applications. Back in the day, one application crashes and everything is stuck. Improvements here are part of user experience, though not directly UI.
4. Less crashing and vague errors in my experience, much more refined software (if you pick your choices right).
5. Smooth audio and video, together with much better support for codecs out of the box.
6. Better plug-and-play, no internal isa cards anymore, external all usb or similar.
7. Many more options for free software and gratis software, but choices for commercial still exist.
8. App stores which makes discovery and installation easier for users.
That many things have turned for the worse, does not mean there are no things that turned better.
i'd go as far as to say there have been zero improvements, substantial or minor.
i mean, thank god windows now has three distinct and clashing UI styles in different parts of the OS, i don't know how we ever managed to live with just one.
>You think a throw back Win 95 clones with UNIX-like internals is what modern users want?
They aren't building it for "modern users", they're building it for fun.
To build a usable operating system you need manpower. To get manpower you need money or you need to build a community around an interesting project that people will work on for free. Andreas has managed to do both of these things.
Serenity is not just another UNIX clone, it's a unique project with the idea of doing everything from scratch. The project uses modern tools like GitHub and Discord so there's a larger pool of people willing to join the project. Had it been all on mailing lists it would be nowhere near what it is today.
Prove “fun” isn’t just an emotional equivocation to burn resources living in one’s nostalgia only to quickly abandon it like numerous attempts at amiga and commodore style OS clones being built for fun in the 00s
If it’s not for modern computer users and lacks a meaningful ecosystem of software and purpose its first worlders avoiding contributing to real work they externalize on others
There’s enough academic wank in the world. Better to focus on pushing computing forward for the aggregate than serve personal ego
Oddly enough, other people find enjoyment in things you might find pointless. Maybe just let them be? Not every waking second needs to be spent on "pushing computing forward" or whatever. Sometimes we just want to do something cool, even if it's useless.
It's not complaining about having a different opinion, it's that the way you present it is vitriolic. It doesn't matter (at least to me) if you don't like the project or don't see the point. There's just no reason to insult and demean the project and its creators.
Ironically this was what caused Workplace OS and Pink/Taligent to fail. It was exactly trying to build a Win 95 clone with UNIX-like internals. One of the biggest failures in modern software development.
We need more optimism in technology, more looking forward and inspiring the next generation to leave their mark; not pining for a past that’s already been here.
Nobody younger than an older millennial who grew up learning computers via Windows 95 has any interest in “retvrning” to this ethos of computing. Hell, I just described myself and even I could care less about this project other than a passing “huh that’s kinda neat” which is a rather tepid response proportional to the work that has been invested here.
There are far more interesting projects rethinking the OS right now that are actually trying their hand at unique architectures. This is just an homage to nostalgia (a technically impressive one, but still nothing inspiring here). The saddest part to me is I’m not sure the graybeards on HN will ever really get that.
In the classic definition of .... "graybeards"... we have no nostalgia for Win95.
Back then we were fighting tooth and nail to undermine MS's monopoly, and Linux as you see it today is the product of that.
I will admit the first times I saw the Win95 interface I found it appealing. Though they actually cribbed a lot form the NeXTstep UI, and I'm much more fond of that.
I prefer the Sun OpenLook UI for nostalgia value, myself.
When I first saw screenshots of Win95 I was impressed at a certain level, from a pure look & feel POV.
But there are certain (non)usability things it introduced which I didn't think were great, actually. Window close button next to the minimize and other controls. Classic MacOS did it right by putting it on the far other side of the window where you couldn't accidentally click. The Start menu broke the whole OO metaphor by adding a deep tricky menu system. Right-clicking context menus all over the place. Task bar at the bottom dynamic depending on what is running means hard to use muscle memory and predict where a given tile will be.
Overall it was very good for the time. Though in fact I personally think the more 'flat' and minimalistic interface of Windows 3 aged better. This faux-3d bevels etc thing didn't age well. Was a novelty product of the time that NeXT kinda began and everyone followed for a bit.
The actual "operating system" (really a shell for MS-DOS) in Win95 was terrible.
As I grow more and more disillusioned with modern computing, I catch myself thinking “just give me macOS classic with a few nice-to-haves bolted on, like a modern browser.” (Yeah, I know those nice-to-haves are probably a lot more work than the rest of the OS).
> They aren't a load of fuddy-duddies who insist on using mailing lists and IRC. Nobody wants to collaborate with a load of grumpy greybeards
Sometimes the grumpy greybeard fuddy-duddies act as they do due to experience. One can have mailing lists which are very distributed and easy to put on a searchable web page somewhere. One could also tie everything to Github or Gitlab or Atlassian, and then have it pulled, or have rates jacked up, or whatnot. One can go on IRC, and easily migrate from Freenode to Liberanet if need be. One can also go into the walled garden of Slack or Microsoft Teams or some other proprietary format, so that some company can hike rates or pull the rug out at their convenience.
I disagree. It’s driving progress in GPU support and acceleration, Image format support, standard lib stability. These all happen under the hood of the os and aren’t particularly flashy. But, the architecture of Serenity and Ladybird means that a lot of the core lib stuff is immediately available to the rest of the is and user space.
Good recommendations. OSes today are more than kernels. Filesystems, init systems, shells, and the configuration conventions would all be part of it. And probably also the windowing system and desktop environment.
The most innovative concepts historically would be Plan9, BeOS, and seL4.
Plan9's approach of "everything is a file" is something that was unique.
BeOS's extensive use of journalling and metadata in the filesystem gave it big advantages.
seL4 being the most rigorous application of a micro-kernel architecture, and making use of formal verification make this one stand out.
Capability-based operating systems also offer immense benefits.
Fuchsia and Redox are clearly drawing some inspiration from these. Along with GNU Hurd, which you didn't mention.
As for shells, nushell is clearly revolutionary. Something that points to what a better world might have been.
I would also recommend looking at Lennart Poettering's vision that extends on innovations like cgroups, journalling filesystems, ostree, etc.
And of course, Nix and Guix both align with this vision of reproducibility, statelessness, and transactionality... along with Fedora Silverblue.
I kinda think of this as making the filesystem work more like git. A distro is a branch. A rollback is a branch from a previous commit.
And then the build system would be completely idempotent... every compilation from any system would be byte-for-byte identical, and thus verifiable in a security sense. And every upgrade on any system could be undone.
I read somewhere long ago that there's some chemical released when you talk about your plans, similar to the chemical that gets released when you complete your plan. So when you talk about your ideas, you feel like you've already accomplished them.
Ever since I heard this, I've been protective of what I talk about and it seems to have helped me ship more things than before.
For me I feel like a large part of it is that no one else shares the same excitement that I do. If I share something I think is really cool and everyone is like “I don’t get it”, those thoughts inevitably just murk my brain.
I agree. I've learned that it's best if I don't tell people my ideas until I've at least started to work on them unless I need to pick someone's brain.
What I want is to be free of the desktop metaphor and the notion my computer is an office job data entry terminal only.
Am working on a GPU accelerated application to replace Gnome. Currently boots to a blank 3D canvas, like opening a new Blender project. Am working on using AI and a planner system to generate a viable user interface given user prompt. Users fill out the plan with possible states and relevant actions, go back and forth with AI to get there.
All runs locally and is loaded by x11 instead of the usual desktop options.
That teaches how to compile Linux kernel and software, not to create an OS out of thin air.
The go-to guide for anyone that wants to build their own operating system has always been the OSDev community wiki and forum: https://wiki.osdev.org/Main_Page
To be fair there is a lot you can do in userland. Graphics protocols, package management, isolation, security etc. And even more can be done by incrementally patching the kernel where needed.
It's just that Linux is kind of usable out of the box with just the kernel and /bin/sh. But for other OSes this isn't true, the kernel can expose a vastly different interface than the actual os which users interact with.
I've done every bit of the kernely/cgroupy/bpf/vfio/syscall stuff for a long time and I honestly don't think I could tell you pretty much anything about building an OS.
I actually came into this thread thinking, "damn, I have no idea specifically WHAT I would do/not do if I made an OS, or where to even start" not that I could at all. But I mean feature-wise, etc. Like, it's obviously a ton of apis that you call to invoke things at the system level but I have no idea what to do at the system level. Maybe you just communicate with APIs over there for everything on the motherboard. I know Nvidia has NVAPI I've used that a bunch through their SDK, not more low level. And you start with probably a super baby kernel..
There are also different styles of OS, like windows with the registry which I have broken and fixed thousands of times, and then nix which is pretty much file based. I don't know what else would be better than either of these, I hate the registry thing but maybe it has some huge benefit I haven't figured out.
When I look at C I see heiroglypics. Maybe me learning rust is helping with that. I do really need to learn it for security sake and (live)patching, etc. I write go and ruby so I don't touch memory much.
I'm the same about filesystems. I know a bunch of them and hve done tons of performance testing for SANs etc but couldn't tell you a thing about the lower level, making one, stuff.
edit: lol I guess a lot of this is installing drivers too
Don’t look at c specifically, look at syscalls. This is the real api of the operating system. It will also be confusing probably, since it is in some senses like thinking about how functions are implemented in assembly, but you don’t have to focus on the mechanics of how they work if that confuses you. One interesting exercise might be thinking about how syscalls are used to make up the standard library functions you are more familiar with.
I have always found it interesting how people who come from the top down (software -> hardware) get confused by the low level stuff, and myself who came from the bottom up (hardware -> software) gets so confused by non-low-level code. I.e. I have no idea how to write a program for windows, it's totally alien to me and I cannot make sense of the code.
Perfect! I've worked with a lot of C kernel security devs and I don't think I've ever seen one of them write something not Cish, like python/ruby/go/etc.
So, what exactly happens here - you need to write a kernel in some super fast low level language like C. I THINK The kernel that you write is probably talking to, for instance an Intel/AMD CPU, Motherboard, GPU, etc API to access the hardware.
Is this close/wrong?
If I made a completely new kernel how do I boot it? Does the kernel have its own API that the BIOS calls? Does the BIOS have anything to do with the kernel but instead something starts Windows and that loads the kernel? I think the kernel mounts/becomes aware of all of the hardware (apis?) potentially by the motherboard telling it what's on it. Does the BIOS just start any C app you point it at and they're just C apps that start the kernel?
Maybe it goes through the motherboard for most of it.. Maybe it accesses every piece of hardware directly without an API somehow?
This may be stupid questions but hopefully they make sense.. And thanks if you or anyone has input!
edit: There's a Boot processing of linux Wiki [1] thats pretty good
> After being loaded into RAM, bootloader (also called first-stage bootloader or primary bootloader) will execute to load the second-stage bootloader[2] (also called secondary bootloader).[6] The second-stage bootloader will load the kernel image into memory, decompress and initialize it then pass control to this kernel image.[2] Second-stage bootloader also performs several operation on the system such as system hardware check, mounting the root device, loading the necessary kernel modules,...[2] Finally, the very first user-space process (init process) starts, and other high-level system initializations are performed (which involve with startup scripts).[2]
> For each of these stages and components, there are different variations and approaches; for example, GRUB, coreboot or Das U-Boot can be used as bootloaders (historical examples are LILO, SYSLINUX or Loadlin), while the startup scripts can be either traditional init-style, or the system configuration can be performed through modern alternatives such as systemd or Upstart.
> The intermediate stage loader (stage1.5, usually core.img) is loaded and executed by the stage1 loader. The second-stage loader (stage2, the /boot/grub/ files) is loaded by the stage1.5 and displays the GRUB startup menu that allows the user to choose an operating system or examine and edit startup parameters. After a menu entry is chosen and optional parameters are given, GRUB loads the linux kernel into memory and passes control to it. GRUB 2 is also capable of chain-loading of another bootloader. In UEFI systems, the stage1 and stage1.5 usually are the same UEFI application file (such as grubx64.efi for x64 UEFI systems).
> Perfect! I've worked with a lot of C kernel security devs and I don't think I've ever seen one of them write something not Cish, like python/ruby/go/etc.
There are a couple of us true full-stack developers but you're very right that we're not common. Programming in low-level languages allow you to think about how, precisely, your memory will be laid out, but on the flip side, they require that you think about memory layouts. If you enjoy thinking about such things, you get used to planning for cache optimization and so on, and moving to python requires actively turning that part of your brain off and taking a „que cera cera" attitude to any performance consideration lower level than big-O notation.
Unfortunately I have never written low level code for a CPU. I have a background in electronics and mainly work with microcontrollers, where everything is C or assembly and you work directly with all the registers in binary/hex.
I know fundamentally it's all the same in regular computers, but I am unfamiliar with the structure of it.
Cool no worries. Embedded stuff is really cool I've always been curious about that stuff on like, assembly lines, etc. I updated my comment you're replying to with a bunch of details if you're interested.
Since OSDev is community project, so I think that says way more about the community than any strong bias on the part of OSDev. That said, a lot of "low level" is concerned with shoving bits around efficiently, not higher level abstractions useful for writing web browsers and such. C (for all it's issues) has a pretty good impedance match for that use case.
The reality is there have always been other languages[1], and not all of them codified the evil stream-of-bytes paradigm. We've been writing OSes in Ada since the 80s. Pascal variants were somewhat common back in the day (e.g. Charles River PERC, CDC Cyber NOS). Apple was on the Pascal train for a long time. Unisys Clearpath is still written (and sold) in their highly extended Algol variant (ESPOL)[2]. I've used OSes written in Modula-2 & Modula-3. There's a number of folks that are trying FreePascal as an OS language.
Of course, there was a healthy LispOS population at one brief, shining point in time (sigh...Genera). Tektronix and a few others had Smalltalk machines.
IBM still writes a lot of low-level stuff in PL/I dialects across it's proprietary product lines (i Series, z Series). Intel wrote it's first ones (e.g. iRMX, ISIS) in a PL/I dialect (PL/M). And CP/M is there too.
Then you can get to the really niche OS writing languages: JOVIAL, anyone?
[1] The source code for some of these legacy OSes is out there. Studying it might be instructive.
[2] Clearpath is the current incarnation of MCP from the Burroughs Large System mainframes (e.g. B5000, B6500, etc.). Stack based and very interesting; now runs as a VM on top of Xeon servers. Not only can you still buy Clearpath, you can download a hobbyist version to try out locally: https://www.app5.unisys.com/library/gmmail/emails/documents/...
The page you link to straight-up has a guide for evaluating if any given language would be suitable to implement a kernel in. How on earth is that unnecessarily married to the idea of "low level == C"?
For a long time, that was what everyone used. But there always were tutorials about other languages - C++, Pascal, even C#. Now Rust is gaining traction.
Have known about LFS for a long time but never messed with it. Would it be suitable for someone who’s not quite up to the task of writing an OS from scratch, but has higher level ideas (e.g. filesystem arrangement/structure) they want to play with?
https://osdev.org/ is an excellent starting point, and if you start to write code to sketch out the components, it's surprising how many features are required. (Not as monumental as writing a database, but nevertheless surprising.)
Going in other directions, consider how Smalltalk, and the Lively Kernel do things.
Gaze in wonder at the power of inertia, and network effects.
I love this but just looking at the comments - while admittedly cool, implementing your own OS isn't black magic or particularly arcane knowledge; sure it's a whole lot of work where you're often reimplementing the wheel, but not outside the realm of any reasonably skilled graduate I would think.
Writing an OS is not any harder than writing a database or a programming language. The complexity lies in how far do you want to go with it.
While not black-magic, dealing with hardware and its quirks is a different skillset than writing React logic. A bug might need a reboot, or in some rare cases with terrible hardware, turning it into a paperweight.
In fact, I believe that learning to write low-level code for simple hardware (say, an Arduino or a RP2040), is a smoother path for a complete newbie than learning the massively complex frontend world, and provides much better foundational knowledge.
The really challenging part when you're building an OS comes from not building an incrementally bigger and bigger mess until you're stuck and can't make any progress any more.
You're right, there's no magic here. It's just lots and lots of work. And there are important decisions to be made about how you design and abstract everything. None of them are hard, but making so many decisions is the very thing that's hard about most programming.
The answer of course is to have lots of programming experience. Which is why building an actual OS to the level of SerenityOS is not something a reasonably skilled graduate would be able to do.
How does one get started on a toy OS? I don’t mean like concepts, but is there like a minimum viable OS .c file somewhere I can look at, with instructions for how to run it on “bare metal”? I assume I need a bootloader of some kind first?
I’m just totally unsure where I’d even begin in a practical sense.
If you're not looking to build a bootloader, but will rely on GRUB then it's extremely simple. You just need to write a very simple multiboot header. It's literally just some numbers that you hardcode at the beginning of your program in assembly.
Then you compile this with GCC flags that tell GCC to not include a standard library (e.g. compile for bare metal).
Then you link with a very simple linker script that tells ld to put the multiboot header before your actual program.
Then, if you want to run on your own hardware, you change the GRUB config file to load your binary and reboot. Or if you want to run in QEMU, you just load the binary with QEMU. Using QEMU is probably simpler, since you're less likely to run into hardware weirdness at the beginning.
Then, you'd start with just writing to a text buffer, which has a hardcoded address on old architectures (it makes sense to start with an architecture where that's the case). That way, you can print stuff to the screen. That's enough to do a lot of very cool stuff already. After that, you configure interrupts, which you do by hard-coding some function pointers in a table using assembly. Then you use some special instructions to load these interrupt handler tables on startup. Now you can do all kinds of interactive things.
That wiki was invaluable to me when I took computer organization courses. My recommendation would be to learn x86 assembly and C (also familiarize yourself with gdb!) by writing programs that run on a Linux system and only after target bare metal programming by using something like QEMU + gdb or Bochs for emulating bare metal hardware that's also debuggable.
(I used x86 assembly as an example assuming you wanted to boot your OS on a PC. An alternative could be to target a well documented SBC like the BeagleBone Black)
I've built three over the decades, but each for very specific use cases and with very specific requirements. It's usually better to use an existing, established OS -- or none at all, depending. But sometimes, a special-built solution makes the most sense.
my hobby os is a fork of inferno, but mostly for dis and the ports structure. i've been slowly working towards converting the userspace into something akin to the old symbolics systems. basically a unikernel/language kernel with AOT bytecode and optional JIT. the project is heavily inspired by the s/m lang ideas originally proposed with LISP.
i had never done osdev-level c-programming when i started on the project, but its been a really fun learning experience.
Considering the use-cases, multi-tasking operating systems are not necessarily going to escape the trend toward information appliances.
In my opinion, if the workstation does survive, than a posix style OS similar to the abandoned HeliOS will become necessary again at some point... as Moore's law is effectively dead, and a 15% context-switching overhead on existing threading and mailbox models is silly.
Using Windows NT or Window 95 as an inspiration would make the task much harder. NT is an absolutely massive, full features, in some sense, and extension of Vax VMS, which itself is extremely feature rich.
I would take the challenge to build something that is the simplest thing that could possibly work.
Dan Ingalls wrote this in the Byte Magazine [1] dedicated to Smalltalk-80 in 1981. Smalltalk is its own operating system, it ran on the 1973 Alto that had 16 core processor and was multitasking. It was the first Graphical User Interface (GUI) that introduced the concept of desktops and window systems to the world. So his observation definitely did not date from before multitasking, GUIs, and window systems and desktops.
Smalltalk and its current incarnation Squeak and SqueakNOS (for Squeak No Operating System) is a virtual machine written in a high level programming language that contains everything that we now call an operating system including its device drivers. It runs on bare metal hardware.
Alan Kay his research group [2] attempted to make an entire personal computer operating system in just 10.000 lines of high level programming language and demonstrated that it is possible to do [3].
[3] answers the question "How would you build an operating system?" from OP.
That was the thinking in the Forth community as well; no absolute frontier between language, library, OS and hardware.
But Ingalls was still wrong, because what actually made that recipe work at that time is that they were programming against a predefined hardware, like game consoles.
When you program for predefined hardware, an OS is basically a one man-month project (well, in the 80s at least).
IIRC 1981 was a bit before the IBM PC, whose selling point was its extensibility. Squeak's VM is exactly a way to come back to predefined hardware.
But of course if you get cocky and think you can rid of the OS because your VM is so funtastic, you end up with an inactive project like SqueakNOS. Either because the hardware diversity the OS protected you from hits you like a truck, or because you place strong restrictions on supported hardware - so not everyone who is willing to try it, can actually try it. That's very few people.
Its best hope to evolve from the PoC stage is to be paired with some hardware product. Like Forth when it was chosen for the OLPC project.
Huh? Multitasking dates back to the time-sharing systems of the '60s.
Granted, while windowing systems existed in '81, they weren't widespread yet (Wikipedia lists PERQ as the first commercially released GUI workstation in '79).
I would not. I would use Linux and its ecosystem as a base. Use a very hackable window manager that allows me to customize the window management and overall experience to my liking. Write a collection of scripts and programs that allow me to do things faster. Maybe release a distro with all of this together ready to use.
I'd focus on high level APIs, managed code and JIT, and stuff like that, and everything would be written in Rust plus a scripting language for everything that isn't performance critical.
More realistically, I just wouldn't build an OS either. That would be a nightmarishly large project!
I would have a UX processor that handles video, sound, and keyboard/mouse inputs. That system would be very fast so the user would never again click only to see the click register on something else.
CREATE TABLE filesystem(inode AS BIGINT UNIQUE NOT NULL PRIMARY KEY, is_dir AS BIT(1) NOT NULL, name AS VARCHAR(4096) UNIQUE NOT NULL, in_this_dir_inode AS INT NOT NULL, bloblist_ptr AS INT NOT NULL, metadata_ptr AS BIGINT),
CREATE TABLE bloblist(blob_id AS INT UNIQUE NOT NULL, onwer_inode_ptr AS INT, thisblob AS LONGBLOB, prev_blob_ptr AS INT NOT NULL, next_blob_ptr AS INT NOT NULL)
CREATE TABLE file_metadata(metadata_record_id AS BIGINT UNIQUE NOT NULL, created_at AS DATETIME NOT NULL, last_accessed at AS DATETIME, last_modified_at AS DATETIME, owner_uid AS INT NOT NULL, owner_gid AS INT NOT NULL, mode AS BIT(4) NOT NULL)
You're mixing up IBM z (mainframes, z/OS) with IBM i (AS/400).
The latter has a single level storage system where disks and memory are part of single address space, and a variant of DB2 database is part of core OS thus making it common to use SQL for many things people wouldn't expect.
AFAIK it still uses a classical file system, just with a DQL system layered on top. I am talking about completely scrapping the idea of file systems, folders, the lot of it. A central database that stores all blobs, configurations, info, and other metadata (modified, created, revision history, diffs, keys, tags, and authority). This would enable real time distributed scalable systems, potentially immutable backups, and a lot more (such as fully auditable data transfers, messaging, access, and more for rapid debugging).
If an operationg system was built today for tomorrow it would certainly be built on/as a database.
Z doesn't really have files or databases, but rather an emulation of variable-length records contained within a relatively fixed allocation on disk. Mainframe DASDs also have a much richer interface than just read/write a given block; for example, you can scan for records within a track that have a given prefix
I would like to scrap the idea of a file and replace it with an object. If it's a "file" it just regurgitates it's contents, but it could also return aspects of itself, decrypt itself, stream from an offscreen resource. Just let them be smart, and what we know as sending "files" would just become object serialisation.
I'm curious of what the fully developed OS will look like for spatial computing if that's what we're calling it now. I think it will have to be built on old methods people are familiar with, like 'clicking' on something with their finger or hand, but I'm fascinated to see when someone is reading the paper newspaper and wants more detail, so they click on the 'link' (ie word/phrase) in the paper and their headset brings up a website with more detail on what they're reading. It could even be older books without any specially marked keywords or anything, as in the physical world would stay exactly the same. Perhaps with people looking at a building and 'clicking' on the building could bring up the tax map or contact info for the building, etc. As time goes by the building would be viewed from all sides, making it a truly 3D model, so you could click on it from any side. An OS on the past with the physical, based on the past with the web, but with the future integrated. I am truly excited to see this built out over the next few years.
Apparently io_uring has been a security nightmare to the point that Google disabled it. I don't know the details but you'd definitely want to ensure you aren't repeating those mistakes.
It's a new way to submit commands, and there are tons of teething issues. Especially considering that Linux had not been designed to work with async APIs from the beginning.
These are not fundamental issues, but definitely something that should be kept in mind.
The Ladybird browser project - https://news.ycombinator.com/item?id=39271449 - Feb 2024 (228 comments)
OP discussed at the time:
Serenity OS: Interview - https://news.ycombinator.com/item?id=30214371 - Feb 2022 (52 comments)
Corecursive: Serenity OS with Andreas Kling [audio] - https://news.ycombinator.com/item?id=30176123 - Feb 2022 (3 comments)
There's a big list of related links at https://news.ycombinator.com/item?id=30858768 but it's a couple years old now.