> I've yet to see a use case that couldn't be handled with either threads, or spawning another process - after all, those are the only APIs you get elsewhere.
Android uses this to pre-load framework resources and code in a way that lets all applications share the backing memory. And when applications crash, they don't bring down the initial process that preloaded everything (so it can continue spawning new apps).
How would you handle that with only threads or spawning another process?
It's possible to share memory between processes that weren't originally forks - consider e.g. X clients using XShm to communicate with the server, or jk for fast communication between apache and tomcat. I guess forking lets you do "share everything, COW", which is kind of handy, but it's also a very lazy way of programming; you get access to the whole address space, so it relies on the other processes to not reuse data that doesn't make sense when shared. Better to only share memory that processes explicitly want to share, and make it clear which one owns any given region of memory.
Shared memory also means that any modifications are also shared, which is really not good in this case. We could mark the sections RO I suppose, but then we have them occasionally copying things out of the RO pages to modify them which just bloats the address space (though doesn't change the number of backing pages). It's also slightly more brittle because you have to be careful about marking everything shared RO.
> Better to only share memory that processes explicitly want to share, and make it clear which one owns any given region of memory.
We are only sharing memory that we explicitly want to share: we load only what we care about, then fork.
That requires that any shared data be included as static data inside the compiled object file, right? Very often, you want to load "code" that is really data in an application-specific format, eg. DEX files on Android, .class files for Java, script text for Python, or templates for a webserver.
Android uses this to pre-load framework resources and code in a way that lets all applications share the backing memory. And when applications crash, they don't bring down the initial process that preloaded everything (so it can continue spawning new apps).
How would you handle that with only threads or spawning another process?