On Sun, Aug 1, 2021 at 8:19 PM John Cowan <cowan@ccil.org> wrote:
On Sun, Aug 1, 2021 at 8:13 PM Andrew Warkentin <andreww591@gmail.com> wrote
To start the child the parent would either
call exec() to start the child running a different program, or call a
new function that starts the child with a parent-provided entry point
and whatever memory mappings the parent set up.
 
This is what I plan to do on the OS I'm writing
(manipulating the child's state won't require any additional
primitives beyond regular file I/O since literally all process state
will have a file-based interface).

In that case you don't need *any* primitive except create_empty_process(): you can do exec() by opening the file, writing to /proc/<child>/mem and then to <proc/<child>/pc-and-go.

Sadly, that's not _quite_ true. You still need some primordial way to get the system going.

Once you have a proc_create and a make_proc_runnable system call, it seems like it opens the door to doing all kinds of cool things like moving binary parsers out of the kernel and into user space, but consider how `init` gets bootstrapped: often, there's a handful of instructions that basically invoke `execl("/bin/init", "init", 0);` that you compile into the kernel; on creation of process 1, the kernel copies those instructions into a page somewhere in user portion of the address space and "returns" to it; the process then invokes /bin/init which carries on with bringing up the rest of the system.

Now you're confronted with two choices: you either put a much more elaborate bootstrap into the kernel (in this day and age, probably not that hard), or you have a minimal bootstrap that's smart enough to load a smarter bootstrap that in turn can load something like init. I suppose a third option is to compile `init` in some dead simple way that you can load in the kernel as a special case, and invoke that. This problem isn't insurmountable, but it's a wide design space, and it's not quite as straight-forward as it first appears.

As I mentioned in the email I linked to earlier, Akaros implemented the proc_create/proc_run model. It really was superior to fork()/exec() and I would argue superior to spawn() as well.

        - Dan C.