Smallest Operating System!
-
- Posts: 12
- Joined: Wed Dec 19, 2007 6:40 pm
@Dex, So far Minidos is the most useful, complete OS at that size that I have ever seen. Even with all of the Int 21h functions coded I doubt it would be much bigger than it is currently.
@ everyone else:
What is wrong with making an OS as small as possible? Perhaps one could be developing something for embedded systems or perhaps an operating system for a game, that is distributed on a CD with the game (I.e. running a computer like a playstation) so that maximum size is left for the game.
Look at menuet OS It certainly does alot for it's size...
@ everyone else:
What is wrong with making an OS as small as possible? Perhaps one could be developing something for embedded systems or perhaps an operating system for a game, that is distributed on a CD with the game (I.e. running a computer like a playstation) so that maximum size is left for the game.
Look at menuet OS It certainly does alot for it's size...
The big problem is if you try to make a semi-decent OS in protected mode. If you really want to keep it tiny, as said above, you probably need to stick with real mode (even though it is slow).
In PMODE, if you were doing it for real, you would need to set up a PMODE interrupt table. It would have 256 entries, and you really would need 256 individual interrupt handlers to put in it. Each handler would take 6 bytes (at a minimum) -- so that would be 1.5K right there. Then you would either need a table of handler entrypoints, or a complete hard-coded IDT table. So that is another 1K or 2K. So 2K to 2.5K in any PMODE OS is going to be dedicated just to setting up a generic interrupt table, unless you try doing some not-recommended programming shortcuts, or using data compression to meet the 4K goal.
And on a machine with 4 or 8K of L1 cache, a tiny OS will run significantly faster, because of the lack of cache refills. So a tiny kernel does equate to a fast kernel, generally -- unless you program it badly.
In PMODE, if you were doing it for real, you would need to set up a PMODE interrupt table. It would have 256 entries, and you really would need 256 individual interrupt handlers to put in it. Each handler would take 6 bytes (at a minimum) -- so that would be 1.5K right there. Then you would either need a table of handler entrypoints, or a complete hard-coded IDT table. So that is another 1K or 2K. So 2K to 2.5K in any PMODE OS is going to be dedicated just to setting up a generic interrupt table, unless you try doing some not-recommended programming shortcuts, or using data compression to meet the 4K goal.
And on a machine with 4 or 8K of L1 cache, a tiny OS will run significantly faster, because of the lack of cache refills. So a tiny kernel does equate to a fast kernel, generally -- unless you program it badly.
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
You'd only really need the exception handlers, which means you only need to store 18 (IIRC) handlers. You can assign a generic kill-this-program handler to the majority of exceptions, which reduces the load to 6 bytes for a dummy handler, and some 20 bytes to generate an IDT from scratch.bewing wrote:(...) you would need to set up a PMODE interrupt table. It would have 256 entries, and you really would need 256 individual interrupt handlers to put in it. Each handler would take 6 bytes (at a minimum) -- so that would be 1.5K right there.
I think you could if you wanted too, get a usefull pmode OS to be 4k in size.
If i can fit my pmode vesa demo, along with CdPayer in the bootsector of a floppy.
Than i say its possible;
Also take a look at this its a superb 3d game, thats only 96k.
http://www.theprodukkt.com/kkrieger
If i can fit my pmode vesa demo, along with CdPayer in the bootsector of a floppy.
Than i say its possible;
Also take a look at this its a superb 3d game, thats only 96k.
http://www.theprodukkt.com/kkrieger
- Attachments
-
- gui1.gif (29.9 KiB) Viewed 3826 times
I don't have a set goal for making my OS as small as possible, but I don't like to waste space either. Sure, HD's are cheap, but try telling that to an OS running on a 16kb PIC micro chip with 1k of onboard ram, or a pocket PC with pretty limited space. I am not going to put a huge amount of useless crap in my kernel because I have the space, I am going to keep it lean so I can fit more of it in the processor's cache so I have less misses and a faster running OS, I am going to optimize my algorithms the best I can for useability, size and speed (in that order). I have made a really small OS, it wasn't a 'feature', it was just small because it wasn't bloated. sub 8k for my 32-bit fat12/16/32, preemptive multi-tasking demand page loading, ide driver, keyboard, mouse and vesa drivers was pretty good, I'm sure I could do better if I was shooting for as small as possible, but that wasn't my goal. The OS can load tasks, driver modules, etc, the tasks can talk to driver modules or the kernel, find functions that it needs, etc. I didn't design it to be small, but I didn't design it to waste huge amounts of space either. Setting your goals high has nothing to do with writing efficient code, if you really have high goals, then set the goal to not bloat your code and waste resources.packet50071 wrote:I don't see the whole point in making a tiny tiny tiny OS !! cause where I live hard drives are cheap as hell -- If u just looking for challenge thats really cool
I set my dreams really high LOL
As far as the IDT is concerned, I only genearet the entries I require, I don't use to many either, definetly not the entire thing, and I allocate space dynamically, then set each function address that requires it. I have a generic function that I initialize all my pointers to on allocation, then for most of my interrupts, I have a call-back method, where you give it the function pointer (replace the generic crap), and when that interrupt is signaled, it stores registers, calls the function, then pops reg's and iret's back. My generic function does nothing, just a ret so takes very little room, and it allows my drivers to supply their own functions (like my ATA/IDE driver uses int 14/15, my memory manager catches page faults, etc. I don't have to make any changes to my kernel to add drivers to handle other interrupts easily, and it can be any type of function that returns with a normal ret (so, asm, c, c++, whatever). I haven't checked the size of my interrupt code, but it's nowhere near the 2k or 2.5k like suggested earlier and it has plenty of functionality. Not recommended shortcut's, what do you consider a shortcut for interrupts? Any one of my drivers can issue an int ?? and it will just do nothing and return (I used to have it print debug info so i could just do an int 0xff and see the debug outputs from anywhere) without crashing, but if user code is calling interrupts that it shouldn't be then that isn't a problem for my kernel, just the program itself, I may put code to terminate any program calling an un-supported interrupt via the generic function, but for now it's fine to just return and move on and/or print some debug info.
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
One of my goals with Clicker was to avoid "arbitrary limits" at all cost. E.g. nothing like a "grand total of N openend files are allowed" or "sorry, there are just too many threads, you can't start another one".
It turned out that i needed trees or similar structures where most "small OS" would just have an array -- so my design choice wasn't really in favour of small code.
You may call it bloated, of course. The intent was to pick up internal datastructures that could "scale" with the number of element they have to store (e.g. don't store things in a way that require walking a list of N items to find the one you need), which again, makes insertion/deletion code bigger...
Another source of code size increase is typically the need for plug-ins or drivers. Writing efficient and small FAT12/16/32 code for ATA disks isn't too hard to achieve. Having efficient implementation of a file system that can support FAT, EXTx and exotique filesystems in ATA/ATAPI, SCSI, floppy, or over (todo) USB, and that loads the appropriate items as they are used requires a completely different approach.
It turned out that i needed trees or similar structures where most "small OS" would just have an array -- so my design choice wasn't really in favour of small code.
You may call it bloated, of course. The intent was to pick up internal datastructures that could "scale" with the number of element they have to store (e.g. don't store things in a way that require walking a list of N items to find the one you need), which again, makes insertion/deletion code bigger...
Another source of code size increase is typically the need for plug-ins or drivers. Writing efficient and small FAT12/16/32 code for ATA disks isn't too hard to achieve. Having efficient implementation of a file system that can support FAT, EXTx and exotique filesystems in ATA/ATAPI, SCSI, floppy, or over (todo) USB, and that loads the appropriate items as they are used requires a completely different approach.
Scaleable data structures doesn't mean large code, just use good algorithms and easy to re-use code/sections. I can allocate any # of pages to store processes or disk/partition info, doesn't mean my algorithm needs to be huge, just need to implement a re-alloc function, or use a linked list or dynamic array (for things that don't change often). I have more than 1 filesystem driver for my 8kb OS, both are simply loadable modules, the kernel reads the first sector of the disk/partition and calls each currently loaded FS driver with a "CanSupport" function, which uses the first sector to determine if it can handle that file system. Once it finds one that does, it passes along a pointer to the i/o driver that reported the block device, so when the FS is invoked it uses the functions from the I/O driver. My Fat driver is used with both my ATA/IDE driver and my floppy disk driver without issue, and my other FS driver uses both of those i/o drivers just the same (my other FS is a custom one that I was using before I implemented fat). So, it's completely extensible, no limit on sizes, yet isn't overly huge. My FS doesn't care how the readblock/writeblock functions are done, it can be through any medium from floppy, ide, cd-rom, network, serial, whatever, it just doesn't care. I first load all drivers, then invoke each i/o driver's init function, which returns a list of however many disk/partitions it finds, and searches for the FS that can support it. Once it finds the correct FS driver, the FS driver registers that section as a volume, and has it's structure filled in (things like block size, read/write flag, total blocks, and the read/write block functions). Also, the drivers don't care when or what order they are loaded, i can load a USB driver after the OS is running, invoke it's init fnuction to search for partitions on a device, it will then search for the correct FS driver for each partition found, and begin working properly. I can load FS drivers at any time, but currently don't have a method to load them as needed (since it doesn't know what's needed unless the FS driver says it can support it). I was going to write FS stubs that are small functions just used to detect support that are all loaded, then the driver itself is only loaded if it finds a device that needs it, but dumped that kernel and started re-writing everything from scratch anyways . Tree's are ok, so are array's, so are linked lists, whatever works for you is fine, none of the above are size limited. Arrays can be re-allocated if it's not done to often (as memory allocation/deallocation is slow sometimes), and if you need to remove/insert a lot, you either need a flag or similar for each element to say whether it's active, and have to traverse the entire list each time (slow for large lists!). Any of those methods is very easy to implement without creating a huge code base and wasting megabytes of memory. I have not put limits on myself, but do try to keep everything small and fast. I would only tell someone they can't open any more threads if they ran out of ram and swap space and couldn't allocate any more memory to create the thread! I also re-use code if possible, if you know you want to store a bunch of tree's, make a generic function to insert/delete from tree's and use it over and over again, that way you only made it a little bigger to add functionality to a lot of your OS parts. My virtual memory manager and physical page manager both use similar functions, so i merged them. I use bitmaps for the allocation, so, i have 2 main functions, allocate and free. If I pass it my struct for my physical page manager it will use the physical base address to start allocations and physical page bitmap to find the next free page (or consecutive pages) and return its physical address. If I pass in my struct for my virtual page manager, it does the same thing except returns the virtual address. No need to write it twice, just a tiny extra thought to make them the same . And now I can add extra tables easily, if I wanted a sub 1mb manager, i just set it's base address to wherever i want it to start (say I want to leave real-mode interrupt vector alone + bios info alone), I can start it after the bios info block up to 1mb. Then I can have a 1mb-16mb table, and another for > 16mb, and all use the same functions, yet just made my kernel much more useful for legacy devices, and barely made it grow at all.Pype.Clicker wrote:One of my goals with Clicker was to avoid "arbitrary limits" at all cost. E.g. nothing like a "grand total of N openend files are allowed" or "sorry, there are just too many threads, you can't start another one".
It turned out that i needed trees or similar structures where most "small OS" would just have an array -- so my design choice wasn't really in favour of small code.
You may call it bloated, of course. The intent was to pick up internal datastructures that could "scale" with the number of element they have to store (e.g. don't store things in a way that require walking a list of N items to find the one you need), which again, makes insertion/deletion code bigger...
Another source of code size increase is typically the need for plug-ins or drivers. Writing efficient and small FAT12/16/32 code for ATA disks isn't too hard to achieve. Having efficient implementation of a file system that can support FAT, EXTx and exotique filesystems in ATA/ATAPI, SCSI, floppy, or over (todo) USB, and that loads the appropriate items as they are used requires a completely different approach.
Having a disk i/o driver that can load while the OS is running or as needed isn't much different than one that loaos on startup, and you don't need special case code all over the place for it, just seperate the functions, your Fat/Ext2/etc file system shouldn't care one bit whether it's reading from an ATA, scsi, floppy, usb, or whether that device was present at startup or just initialized, there is no reason why it should care, and if it does care, you might want to re-think your implementation so you can make everything more conforming. I know that the more you add, the bigger it gets, and the more advanced you make it, the larger it grows, but that doesn't mean it has to be a 2gb OS either. My small fat12/16/32 code works fine with ata or floppy, it doesn't have a special case for either one, it treats any i/o device the same. My fat12 driver could work with any device I wanted as long as it had a few details for it, like block size block count, read/write block, and that's all my FS driver cares about .
- mathematician
- Member
- Posts: 437
- Joined: Fri Dec 15, 2006 5:26 pm
- Location: Church Stretton Uk
Back in the 70's, micro-computers (as they were then known) had just 64kb of memory, and ran an OS called CP/M which occupied 3.5kb for the kernel, and the shell another 2kb. Even so, the idea that you could get a GUI into that amount of space would never have entered anybody's imagination.
MS-DOS with about 32kb each for kernel and drivers, plus another 64kb for the shell, in comparison looked wildly sophisticated when it came along.
MS-DOS with about 32kb each for kernel and drivers, plus another 64kb for the shell, in comparison looked wildly sophisticated when it came along.
If you want to find the smallest OS you might try looking into mainframe OSes.MicrOS wrote:That's what I'm doing, and then, after that a GUI interface over it.zeii wrote:Well, Of course it is possible.
Look at our history ...
Look back at the 60s or indeed, even the 70s.
Hell, look at the 80s.
Its all possible.
It just depends on you
Your skill, your vision,
Specifically, your determination.
~Z
I just want to learn!!
The gui has to be smaller that 10 kbs
I'll get it!!
And maybe the OS will only have a FS and Managment.
It'd be quite simple but'll be able to work as a note keeper and so!!
(Even thought some may think of it as useless)
Anyone or anyhing will make me desist
=)
BOS/360 was about 8K
IBSYS was smaller but I believe GM-NAA is probably the smallest but when you go this far back you have problems defining even memory as some of these machines are really just a few registers and some card readers
Hope it helps
Paddy
Visit www.oshistory.net for information on the history of computer operating systems
CP/M first started in 1974mathematician wrote:Back in the 70's, micro-computers (as they were then known) had just 64kb of memory, and ran an OS called CP/M which occupied 3.5kb for the kernel, and the shell another 2kb. Even so, the idea that you could get a GUI into that amount of space would never have entered anybody's imagination.
MS-DOS with about 32kb each for kernel and drivers, plus another 64kb for the shell, in comparison looked wildly sophisticated when it came along.
http://retrotechnology.com/dri/d_dri_history.html
For GUIs look at GEM/1, Alto, Star and LisaOS, generally the early versions had very restricted resources to work with.
For a video of the Alto
http://www.maniacworld.com/alto-computer-video.html
Paddy
Visit www.oshistory.net for information on the history of computer operating systems
- zaleschiemilgabriel
- Member
- Posts: 232
- Joined: Mon Feb 04, 2008 3:58 am
Thanks zaleschiemilgabriel, thats what i was try to make it look like, but i had to draw it in real time, as you could not fit a bmp image in 512bytes, let alone the rest of the pmode OS.zaleschiemilgabriel wrote:The smallest operating system I ever saw was 0 bytes in size, although it always displayed this peculiar message for no reason: "Missing Operating System".
@DEX: Nice screenshot! It looks like an iPod.
Its called "CdPod".