Page 1 of 2
simplest possible design
Posted: Sat Oct 30, 2021 2:18 am
by kerravon
I have just completed proof of concept for PDOS-generic.
This uses an existing host system as a glorified BIOS, and
essentially exports the host C library so that the emulated
disks can be accessed using standard fopen/fseek/fread/etc.
The OS in turn exports an independent C library for use by
applications, which are subsequently tiny.
There is no emulator required, and the code runs at native
CPU speed. The disks are still emulated by host files though.
All code is portable C90 so you can take this MSDOS-like
environment to any alien environment.
I have Windows downloads available at the bottom of
http://pdos.org
The main source file is here:
https://sourceforge.net/p/pdos/gitcode/ ... ric/pdos.c
I'm interested in any technical analysis.
Thanks. Paul.
Re: simplest possible design
Posted: Wed Dec 01, 2021 4:41 am
by eekee
I don't think I'm qualified for technical analysis, but from a user's perspective I always like operating systems which can run under another. They have the potential to let you use a consistent environment anywhere. As for this one, with no CD/CHDIR and DIR not accepting any arguments, I can see it's early days yet. Is PDOS on hardware this limited, or is this not the same command.com? I'm curious about the virtual files MINIHD B S and SYSTEM~1 (if that's what they are).
Re: simplest possible design
Posted: Wed Dec 01, 2021 5:12 pm
by kerravon
eekee wrote:I don't think I'm qualified for technical analysis, but from a user's perspective I always like operating systems which can run under another. They have the potential to let you use a consistent environment anywhere.
Yes, I'll be able to take all my tools with me too.
As for this one, with no CD/CHDIR and DIR not accepting any arguments, I can see it's early days yet. Is PDOS on hardware this limited, or is this not the same command.com?
It's not the same as the one from PDOS/386. PDOS/386 has all of the above. I just need to bring that functionality across. It's not a straightforward copy though, so I'm still waiting to make sure the technical analysis is done before I begin that work. If you want to see what PDOS-generic will eventually look like, just run PDOS/386 instead.
I'm curious about the virtual files MINIHD B S and SYSTEM~1 (if that's what they are).
The "dir" command is a crude listing of the directory. "MINIHD" is a volume label, and "SYSTEM~1" is the short name for "System Volume Information". It works properly in PDOS/386. Basically PDOS-generic is intended to be how PDOS/386 should have been written from the start, if I knew what I now (think I) know. I should have provided a "bios" layer to the real BIOS, for PDOS-generic. There has been a bit more technical analysis done in that I think the BIOS layer should use the mainframe flavor of PDPCLIB, which deals with "block" devices. But I'll need to restructure PDPCLIB because it's currently either block or character mode, whereas I believe I need both. And I also need to add ANSI escape sequence processing to PDPCLIB (my C library), for the BIOS layer to use, as it can't/shouldn't go into PDOS-generic.
Re: simplest possible design
Posted: Sun Nov 06, 2022 2:09 am
by kerravon
Note that PDOS-generic has had a pretty major conceptual change, combining the OS and BIOS interfaces, plus it has an ARM version now, that allows you to turn your Android smartphone into an MSDOS-like PC (unless you deliberately inspect the binary code), without emulation.
You can get it here:
https://github.com/jeanmarclienher/Pdos ... g/rel0.7.0
Commands available are dir, date/time, copy, type, exit
Re: simplest possible design
Posted: Tue Nov 08, 2022 4:10 pm
by Crono
eekee wrote:I don't think I'm qualified for technical analysis, but from a user's perspective I always like operating systems which can run under another
This unlikely to count as "simplest possible design". Too many uncertanties/dependacies/bugs to handle.
Re: simplest possible design
Posted: Tue Nov 08, 2022 4:53 pm
by AndrewAPrice
The simplest possible OS in my mind (that could actually do something useful and not just "halt") would be a
unikernel.
A unikernel turns the OS into a library. You build your application using the unikernel library and you boot straight into your application running on bare metal.
Imagine vintage video game consoles where there is no OS. You pop in the cartridge and boot straight into the game. The SDK provided by the console manufacturer is effectively a unikernel.
Re: simplest possible design
Posted: Wed Nov 09, 2022 12:12 am
by kerravon
AndrewAPrice wrote:The simplest possible OS in my mind (that could actually do something useful and not just "halt") would be a
unikernel.
A unikernel turns the OS into a library. You build your application using the unikernel library and you boot straight into your application running on bare metal.
Imagine vintage video game consoles where there is no OS. You pop in the cartridge and boot straight into the game. The SDK provided by the console manufacturer is effectively a unikernel.
That sounds like a great idea, actually.
I'd like to support that configuration.
Can you tell me what counts?
First of all, I'm relying on an "ideal BIOS"/pseudo-BIOS/Hardware Abstraction Layer - I'm not sure what the correct terminology is. Part of getting to there is a separate MBR, boot sector, OS loader, at least potentially. Those things can't really be considered a library, but I'm not sure that's actually where the abstraction you talk of takes place.
Can you take a look at main() here:
https://sourceforge.net/p/pdos/gitcode/ ... ric/pdos.c
I can potentially move that into a file of its own, so that PDOS itself is nothing more than an example user of the unikernel.
So it is at the main() level that you can choose whether to even bother to open the hard disk. The FAT functions are there, e.g.:
fatInit(&fat, §[11], readLogical, writeLogical, disk, getDateTime);
(that's in my main())
but you don't need to call it if you don't want to.
I'm not sure what to do about memory - I can have that all available so you can do malloc() or I can say that so long as you don't attempt to open files or anything else that potentially needs to do a malloc(), you can avoid that. I'm not sure that doing that serves any purpose though. It's probably best to just have all memory known to the C library before your main() is hit.
And perhaps there could be a standard for the unikernel? Could we make one up right now?
Thanks. Paul.
Re: simplest possible design
Posted: Wed Nov 09, 2022 12:17 am
by kerravon
Crono wrote:eekee wrote:I don't think I'm qualified for technical analysis, but from a user's perspective I always like operating systems which can run under another
This unlikely to count as "simplest possible design". Too many uncertanties/dependacies/bugs to handle.
Can you elaborate on all that please? I think you're correct about the bugs - this design doesn't protect your application from wild pointers (same as MSDOS), but all that protection (ie paging) is something that makes the OS more complicated.
So perhaps we need to define "simple". Simple to debug? Simple to understand how the OS works? Simple to maintain the OS code? Simple to add debug at the kernel level if something isn't behaving correctly?
By the way, on a semi-unrelated note, I am trying to understand the different concepts myself.
I've made an attempt to isolate all the different concepts, but not reconcile them. You can see that at the top of this file:
https://sourceforge.net/p/pdos/gitcode/ ... ib/start.c
Down to where it says "I give up".
Re: simplest possible design
Posted: Wed Nov 09, 2022 7:40 am
by AndrewAPrice
How are you depending on stdlib.h, studio.h, etc? Are they from the host OS, or do you have an implementing that runs on bare metal (without an OS)? How do you run your OS?
Re: simplest possible design
Posted: Wed Nov 09, 2022 8:55 am
by kerravon
AndrewAPrice wrote:
How are you depending on stdlib.h, studio.h, etc? Are they from the host OS, or do you have an implementing that runs on bare metal (without an OS)? How do you run your OS?
The C library stdio.h fopen() devolves into a call to PosOpenFile(), not much different from POSIX open().
That function is implemented in PDOS (true of both PDOS-generic which I pointed to above, and PDOS/386 which is fully fleshed out).
So it basically calls itself (via static link, not an interrupt). But that's only if the OS wants to open a "config.sys" etc. It's more useful when that same C library is exported to applications, similar to UEFI, rather than a DLL.
There is an unrelated C library exported by the pseudo-BIOS, which provides access to raw disks. For POC that is a host OS basically, but that can be replaced by a bios fopen("0x80", "r+b") in the future on bare metal.
Let me know if you need further clarification.
Oh, and the OS is run by the "ideal BIOS" loading it, similar to UEFI, and invoking it, similar to UEFI.
Re: simplest possible design
Posted: Mon Nov 14, 2022 1:48 am
by eekee
kerravon wrote:So perhaps we need to define "simple". Simple to debug? Simple to understand how the OS works? Simple to maintain the OS code? Simple to add debug at the kernel level if something isn't behaving correctly?
Indeed, it's always good to figure out where you most need to simplify and where you can tolerate complexity. As I've learned by considering how to do without various OS features from memory protection to files, everything you can simplify complexifies something else.
As for unikernels, I agree with vvaltchev when he
wrote that bundling the OS as a library is just marketing. A unikernel is a simple kernel, a library is just one way of packaging it.
Re: simplest possible design
Posted: Tue Nov 15, 2022 8:33 pm
by kerravon
eekee wrote:kerravon wrote:So perhaps we need to define "simple". Simple to debug? Simple to understand how the OS works? Simple to maintain the OS code? Simple to add debug at the kernel level if something isn't behaving correctly?
Indeed, it's always good to figure out where you most need to simplify and where you can tolerate complexity. As I've learned by considering how to do without various OS features from memory protection to files, everything you can simplify complexifies something else.
As for unikernels, I agree with vvaltchev when he
wrote that bundling the OS as a library is just marketing. A unikernel is a simple kernel, a library is just one way of packaging it.
Is there any disadvantage in "packaging" it as a library?
If not, may as well do it that way?
I still need something specific to satisfy people who want a unikernel though.
Re: simplest possible design
Posted: Thu Nov 17, 2022 1:56 am
by linguofreak
eekee wrote:kerravon wrote:So perhaps we need to define "simple". Simple to debug? Simple to understand how the OS works? Simple to maintain the OS code? Simple to add debug at the kernel level if something isn't behaving correctly?
Indeed, it's always good to figure out where you most need to simplify and where you can tolerate complexity. As I've learned by considering how to do without various OS features from memory protection to files, everything you can simplify complexifies something else.
For a given set of responsibilities that you give to a system, there's going to be some minimum number of bits needed to describe a system that can meet those responsibilities, and the size of the HDL code for the hardware, plus the size of the firmware, plus the size of the OS, plus the size of the middleware, plus the size of the application(s) is going to be greater than or equal to that minimum size, regardless of how you divide it up between them. Plus, the information-theoretically smallest description of a system is not always the most convenient, easiest to understand, or most performant implementation of the system. The PDP-8/S was probably the simplest implemenation of the PDP-8 architecture built in terms of number of transistors, or the number of bits needed to describe the physical layout, but a bit serial implementation of a given architecture probably takes more human labor to design than an implementation that has a full width ALU and bus.
As for unikernels, I agree with vvaltchev when he
wrote that bundling the OS as a library is just marketing. A unikernel is a simple kernel, a library is just one way of packaging it.
Well, pretty much any kernel I've ever heard of is basically just a library. On pre-MMU/pre-protection architectures, the kernel was basically a library or set of libraries that provided a convenient software interface to the hardware. With the advent of protection and memory management, the kernel retained the job of "shared library for hardware access", except that now nothing else *could* access the hardware. It also gained the job of providing every process with its own virtual machine of sorts (not in the modern sense of "virtual machine", where the VM has access to virtualized hardware that behaves in the same way as the bare metal, complete with its own protection and mapping capabilities, but in the sense that each process has the illusion of having *a* machine of some sort all to itself). In each "virtual machine", the C runtime (or equivalent) now played the roll that the OS had originally played, acting as a software interface to the "hardware" (i.e, the OS system-call interface).
This, I think, is the problem with microkernels: services that are best implemented as libraries end up shoved out into their own "machines", communicating, after a fashion, over a "network". With a monolithic kernel, the divide between kernel and userspace allows these services to behave as libraries while preventing userspace code from messing with their data. There are ways hardware could be designed to allow services to still be called as libraries while isolating them not only from userspace but from each other, but such designs are not currently common.
Re: simplest possible design
Posted: Thu Nov 17, 2022 6:16 pm
by kerravon
linguofreak wrote:
This, I think, is the problem with microkernels: services that are best implemented as libraries end up shoved out into their own "machines", communicating, after a fashion, over a "network". With a monolithic kernel, the divide between kernel and userspace allows these services to behave as libraries while preventing userspace code from messing with their data. There are ways hardware could be designed to allow services to still be called as libraries while isolating them not only from userspace but from each other, but such designs are not currently common.
Can you elaborate on this a little bit more - would you actually recommend that ideally we move to such hardware in order to get the benefits of a microkernel without the loss of libraries, and can you give an example of a library function that is badly implemented by normal microkernels? Thanks.
Re: simplest possible design
Posted: Fri Nov 18, 2022 7:24 am
by thewrongchristian
kerravon wrote:linguofreak wrote:
This, I think, is the problem with microkernels: services that are best implemented as libraries end up shoved out into their own "machines", communicating, after a fashion, over a "network". With a monolithic kernel, the divide between kernel and userspace allows these services to behave as libraries while preventing userspace code from messing with their data. There are ways hardware could be designed to allow services to still be called as libraries while isolating them not only from userspace but from each other, but such designs are not currently common.
Can you elaborate on this a little bit more ..., and can you give an example of a library function that is badly implemented by normal microkernels? Thanks.
I'd use as an example something like managing virtual memory in a user level server process.
Under such a scheme, even servicing a page fault would require a context switch to another user process to service the paging request, possibly reading the page in from the filesystem (which might itself require another context switch), which further might need to read in data from a disk via a driver in yet another user level process (yet another context switch.)
So, a page fault might require 6 user level context switches (page faulting process -> VMM process -> Filesystem process -> Disk driver process, and back again).
Note, it might be that the read from disk takes a long time, dwarfing the context switch times in the grand scheme of things.
The equivalent in a monolithic kernel requires no context switches.