In another comment, I observe how Go doesn't even have a binding to fork.
Erlang is another example of that. There is no standard library binding to the fork function. If someone were to bash one into a NIF, I have no idea what would happen to the resulting processes, but there's no good that can come of it. (To use Star Trek, think less good and evil Kirk and more "What we got back, didn't live long... fortunately.") Despite the terminology, all Erlang processes are green threads in a single OS process.
> Despite the terminology, all Erlang processes are green threads in a single OS process.
The main Erlang runtime uses an M:N Erlang:native process model, not an N:1. So Erlang processes are like green threads (they are called processes instead of threads because they are shared-nothing), but not in a single process.
I mentioned this somewhere else but I thought Erlang does NOT share memory.
Doesn’t that make Erlang a bit unique. It was the ability to spawn a new process extremely fast AND also have memory isolation. This combination is what the OP was wanting to achieve.
Erlang mostly doesn't doesn't share memory between its Erlang processes, but it does this by making it so there's simply no way, at the Erlang level, of even writing code that refers to the memory in another Erlang process. It's an Erlang-level thing, not an OS-level thing.
If you write a NIF in C, it can do whatever it wants within that process.
The BEAM VM itself will share references to large binaries. Erlang, at the language level, declares those to be immutable so "sharing" doesn't matter. As an optimization, the VM could choose to convert some of your immutable operations into mutation-based ones, but if it does that, it's responsible for making the correct copies so you can't witness this at the Erlang level.
The Erlang spawn function spawns a new Erlang process. It does not spawn a new OS process. While BEAM may run in multiple OS processes per dragonwriter, the spawn function certainly isn't what starts them. The VM would.
So, you can not spawn a new Erlang process, then set its UID, priority, current directory, and all that other state that OS processes have, because an Erlang process is not an OS process. If the user wants to fork for some reason beyond simply running a program simply, because they want to change the OS process attributes for some reason, Erlang is not a viable choice.
Erlang is not unique in that sense. It runs as a normal OS process. What abilities it has are implemented within that sandbox, no different than the JVM or a browser hosting a Javascript VM.
My reference to “fast” was in the context of creating a new process due to the OP post talking about how long fork/etc can take. Not in reference to executing code itself.
In that sense it’s fast in the same way e.g. coroutines(/goroutines) are fast: it’s just the erlang scheduler performing some allocation (possibly from a freelist) and initialisation. Avoiding the kernel having to set things up and the related context switches makes for much better performances.
> I thought green threads share memory but Erlang processes do NOT share memory, which is what makes Erlang so unique.
Erlang processes don’t share memory because the language and vm don’t give primitives which let you do it. They all exist within the same address space (e.g. large binaries are reference-counted and stored on a shared heap, excluding clustering obviously).
> Did Erlang create a so called “green process”?
Yes.
> If so, why can’t this model be implemented in the kernel?
Because erlang processes are not an antagonistic model, and the language restricts the ability to attack the VM (kinda, I’m sure you could write NIFs to fuck up everything, you just don’t have any reason to as an application developer).