AFAIK, those are not 'processes' in terms of operating system processes, but instead some kind of parallel running tasks within the Erlang VM (much closer to threads).
Edit: If you think I am wrong, could you please explain what is wrong?
AFAIK there is very little difference between processes and threads in linux (both are instances of task_struct), the variability in implementation details specific makes that use for classification useless, and thus the only possible separation of any use is semantics: the difference between processes and threads is whether they share internal state (generally / by default).
There is an enormous difference between processes and threads in Linux and it's a fairly simple one - each process is allocated a memory space. All those mappings and page table entries are what makes process spawn expensive.
There is a terminology issue though, you're right, and that comes with using OS terms for userspace scheduling. Go coming up with their own term - goroutines - significantly simplifies the conversations. Gorountines, Erlang processes, green threads and fibers are all fundmentally the same thing - M userspace 'tasks', scheduled on to N operating system threads of execution, likely in one OS process. There are some language details as to how they are presented to the user.
Not sure how it is in Linux, but in Windows it's only threads that can execute code. Spawning a process will cause the OS to create a thread for it as well.
Interesting. My interpretation was more along the lines of having its own process identifier (PID) and to my knowledge, OS processes have that, OS threads don't and I thought Erlangs processes don't get PIDs by the operating system either (although that might be wrong too).
At the kernel level, both "processes" and "threads" have PIDs since they're the same thing. In fact, before NTPL was implemented Linux broke posix because it returned the kernel PID directly when queried[0]. That's no more than an interface choice of POSIX though. And POSIX threads still have a thread id, a (pid, tid) is a unique visible identifier. So the distinction seems completely arbitrary.
And Erlang processes do have (erlang-level) PIDs. In fact, they get (erlang-level) PIDs across multiple machines when in a cluster.
And again I think ancillary properties are not what matter, a PID is a consequence of being a process, not a cause. The cause of being a process is not sharing internal state, that's the useful bit. Erlang's tasks are not os processes (that would rather defeat the points), but it doesn't seem useful to call them "not processes".
[0] it now returns the tgid, a "thread group" at the kernel level is what you see as a process from userland: the tgid is the pid of the original task, creating a "process" will create a new task with a new tgid while creating a "thread" will create a new task with the existing tgid https://stackoverflow.com/a/9306150/8182118 provides an excellent primer on how this works
Traditionally in Unix and Windows contexts, "processes" means separate memory address spaces and OS-guaranteed isolation, and "threads" mean threads of execution that have shared access to one address space.
Erlang processes are threads as seen by the OS, but the Erlang runtime implements process-y restrictions that enforce isolation and forbid shared memory between Erlang processes that do infact exist as threads inside te Erlang VM.
The programming model, as seen by the Erlang/Elixir prgrammer, is thus anologous to Unix processes, just with lower overheads.
The Unix programming model does not forbid shared memory between processes. It just gives them separate address spaces, but aside from that you can do whatever you want. Yes, separating address spaces makes processes memory safe by default, but it's not just Erlang that enforces this sort of memory safety programmatically within a single address space. What about Rust, or Haskell. They don't refer to threads, or to runtime-scheduled fibers created via async programming or via the work-stealing model, as "processes".
I don't know about Haskell parallelism primitives, but in Rust the normal thing to do is to share references to the same memory location correctness-checked by the type system. The correcness guarantees don't come from private storage, but from compiler made proofs done on the control flow / dataflow. So it wouldn't make sense to say "processes".
Erlang is a dynamic language without any such type system checks. The process separation is all just based on the fact that it's impossible to get or make a shared value, it's just not a concept in the language. You send and receive messages, which implies a copy, and you faff around with local values inside your process.
Re shared-memory support in Unix: Yeah, you have escape hatches from the memory models in Unix processes, and Rust, and probably Erlang and Haskell. But they're exceptions and safe to ignore when discussing terminology to describe the platform's native model. Also the Unix shared memory APIs were a late addition to the OS and everyone agrees they're ugly :)
Not true, Erlang processes are userspace threads, not kernel threads. It's an M:N model -- you can run thousands of Erlang processes on a single OS thread. See:
Good correction. But for the purpouses of this discussion re the processy-nature of Erlang processes, it's an implementation detail without difference in programming semantics.
Edit: If you think I am wrong, could you please explain what is wrong?