Consider: two processes can have the same file open for reading & writing at the same time, so some kind of communication is possible between the two.
When process A writes to the file, it first populates a buffer inside its own process-specific memory with some data, then calls
write which copies that buffer into another buffer owned by the kernel (in practise, this will be a page cache entry, which the kernel will mark as dirty and eventually write back to disk).
Now process B reads from same point in the same the file;
read copies the data from the same place in the page cache, into a buffer in B's memory.
Note that two copies are required: first the data is copied from A into the "shared" memory, and then copied again from the "shared" memory into B.
A could use
mmap to make the page cache memory available directly in its own address space. Now it can format its data directly into the same "shared" memory, instead of populating an intermediate buffer, and avoiding a copy.
Similarly, B could
mmap the page directly into its address space. Now it can directly access whatever A put in the "shared" memory, again without having to copy it into a separate buffer.
(Obviously some kind of synchronization is required if you really want to use this scheme for IPC, but that's out of scope).
Now consider the case where A is replaced by the driver for whatever device this file is stored on. By accessing the file with
mmap, B still avoids a redundant copy (the DMA or whatever into the page cache is unavoidable, but it doesn't need to be copied again into B's buffer).
There are also some drawbacks, of course. For example:
if your device and OS support asynchronous file I/O, you can avoid blocking reads/writes using that ... but reading or writing a mmapped page can cause a blocking page fault which you can't handle direcly (although you can try to avoid it using
it won't stop you trying to read off the end of a file, or help you append to it, in a nice way (you need to check the length or explicitly
truncate the file larger)