Should you give up right now? By any means, no!
However, doing it in higher level language, like C, may be a gould advice for the beginning. (You can always change parts of this to assembler, if you mind performance, or for pride, or {insert here}.)
Once, I actually did something much like this, starting from a similar background. Only, in my case, it was for a superficially UNIX alike system that should run in a browser. The latter was then (in 2003) the tricky part, since this was still the browser war and this must support anything from Netscape Navigator 4 and Internet Explorer 4 upwards, and even that new-fangled thing called Firefox (then still in its 0.x days. ) Anyways, my background was/is similar to yours, with about as much insight into UNIX, etc, as you get when dealing with a web server. I even avoided reading up on this, rather, having a try at what I could come up with on my own.
So, in my interpretation, there are a few boundaries to what may considered a OS: The user facing I/O, we receive numeric keyboard codes and in turn write numeric character codes to the console. Then, we want to access and manage files (this was cheap in my case, since these were just stored in variables and the browser was lacking any real storage access) and running binaries (in my case, these were JS scripts, which were called by some glue logic). In the middle of this, you have a file system (I went for the conventional inode and file pattern, where the inode contains the descriptive attributes, and the file the payload), process management and a shell as the magic glue between these components. (I went with the UNIX way of having the current working directory managed by the shell, rather than, say, in the core system, which simplifies things.) Process management had to be cooperative, since I was sitting on top of a single threaded system that was also considered to be the ânativeâ layer.
My advice would be to manage these âboundariesâ first, console I/O and files, and a start mechanism for any processes. Also, you may want to define what goes with a process. E.g., an environment object of sorts is nice to have, and of course, a convention for an ARGV (arguments vector comprising any arguments handed to that process) and code to access this from inside a process. For scheduling, some sort of parent-child relationship is probably a requirement. Youâll probably have at least some sort of top-process, and children, which do their jobs and yield their results and status their parent. In order to chain this up, a process should know about its children and should have a way to yield control and status to its parent.
A good way to start may be to have a console which can receive and parse a filename and type that file, if thereâs any. (This already provides you with code for the essential âboundariesâ.) Then, thereâs still time to invest into more glue logic and make things more interactive, replace the code for typing back the file contents by arbitrary programs/processes, make them replaceable/callable by filename, etc. From this perspective, the tricky and vital âmiddle partâ (scheduling, process management, a more comfortable shell, a full-fledged file system, extending the console to support styles/character attributes, etc) becomes just some more of the glue logic. Iterative refinement is your friend.
Speaking of the console and interactivity, mind that it may be useful to have two modes, cooked and raw, where the former asks for word-like chunks terminated by an ENTER code and allows for line editing (mind that an input line has two ends, when it comes to editing), and the latter is about unprocessed character codes, as may be required for a game or an editor. (And a process should be somehow able to somehow communicate to the console what it is about.)
In a higher language and in a convenient development environment, it can be done actually quite quickly, as, much like when writing a novel, much develops consequentially from what you already wrote and also âcrystalizesâ while you write what comes just before. (For which it is also advisable to have some crude outlines of a plan, right from the beginning.) In my case, I had the essence of what was needed for a console already around and the ârestâ was about two weeks, in which I, admittedly, didnât do much else. (For an excuse, I was curing a cold.)
If you want to visit my youthful sins (this is now more than 20 years ago), they can be seen here: https://masswerk.at/jsuix/ (feel free to have a look at the source, itâs dated vanilla JS w/o dependencies) and a crude outline/description can be found here: https://masswerk.at/jsuix/jsuix-documentation.txt. (This stops with âto be continuedâ.) Finally a compilation of the man entries is here: https://masswerk.at/jsuix/man.txt