== Why the kernel does _mmap()_ (beyond efficiency) I recently read Daniel Ehrenberg's [[Why not mmap? http://useless-factor.blogspot.com/2011/05/why-not-mmap.html]] and ran across the following snippet: > _mmap()_ is a system call, implemented by the kernel. Why? As far as I > can tell, what I described above could be implemented in user-space: > user-space has page fault handlers and file read/write operations. One way to put the reason that the kernel handles _mmap()_ is that there is a good argument that the reason _mmap()_ exists is shared libraries. And *shared* is the operative word here. A kernel implementation of _mmap()_ makes it easy to share mapped objects between different processes, in several different ways. First and most obviously, the kernel can simply share the memory if several processes _mmap()_ the same thing. Such as, for example, much of the C shared library. Second, the kernel can share memory using copy on write semantics; if you map an object 'private', the kernel can still share pages that you don't actually write to. This is commonly used for making necessary per-process modifications to mapped shared libraries, such as relocations or read-mostly data. Third, the kernel can have a [[unified buffer cache UnifiedCacheMmap]] so that it doesn't matter whether processes use _mmap()_ or _read()_ and _write()_, they all see the same thing and the kernel doesn't duplicate memory. It might be possible to emulate the first sort of sharing at user level between cooperating processes (you'd use System V shared memory). I don't think that the second sort of sharing is doable at user level unless you have new address space modification syscalls that allow you to overlay chunks of regular address space on System V shared memory (you'd normally do something like that with _mmap()_ and friends, but we're assuming that they don't exist). The third sort of sharing is impossible without kernel assistance, and I don't think one should under-estimate how important it is; _read()_ vs _mmap()_ coherence is what makes it relatively trivial to replace _read()_ with _mmap()_ in programs. The first and the second sort of sharing are both very important to get full benefit from shared libraries. If you simply load shared libraries into processes without sharing, all you save is disk space; if you share the memory of shared libraries between processes, you also save precious RAM. Back in the days of SunOS 4, with small memory machines and large shared libraries for things like graphics toolkits, this made a real difference. (People did shared libraries with special custom hacks before there was _mmap()_, but _mmap()_ had a number of advantages including being clearly generic and providing a clean answer for how to deal with different processes loading the same shared library at different addresses in memory.)