Incidentally you can use the exact same setup (plush mmap) for interprocess queues.
The advantage of threads is that you can pass pointers to your data through the queue, while that's harder to do between processes and you have to resort to copying data in the queue instead.
>while that's harder to do between processes and you have to resort to copying data in the queue instead.
I could be wrong - I've never done it, but I understood that you can even store POSIX mutexes and condition vars in shared mem so that 2 processes (or more?) can process data without copying, so long as they use the both use the same locks stored in the shared memory.
There are domain sockets if you need something more such as passing file descriptors. Both pipes and sockets (including TCP, with obvious limitations) can be done with zero copy given the right set of flags, thought things get harder if you have a complicated runtime (ie. garbage collection) involved. There's always explicitly mapped shared pages
Threads are an important structuring mechanism: You can assume that all your threads continue to run, or in the event of a crash, all your threads die.
Also, unidirectional pipes aren't exactly sufficient for inter-process / inter-thread synchronisation. They are ok for simple batch processing, but that's about it.