Can some one explain in an easy to understand way the concept of memory mappings (achieved by mmap() system call) in Unix like systems ? When do we require this functionality ?
Concept of memory mapping in Unix like systems
Architecturememorysystem-programming
Related Solutions
I suggest you look into the LDD3 book, it is free. It does explain ioremap in chapter 9, page 249. Also look into APIU 3rd edition, chapter 14.8, page 525. Let me summarize, best to my abilities:
ioremap is a kernel function that allows to access hardware through a mechanism called I/O mapped memory. There are certain addresses in memory that are intercepted by motherboard between CPU and RAM and redirected to other hardware, like disks or keyboard. Not sure if you can use the usual addressing through pointers or some other kernel functions.
I/O memory is simply a region of RAM-like locations that the device makes available to the processor over the bus. This memory can be used for a number of purposes, such as holding video data or Ethernet packets, as well as implementing device registers that behave just like I/O ports (i.e., they have side effects associated with reading and writing them).
mmap is a syscall available in user space that maps a process memory region to content of a file, instead of RAM. When you access that mapped region of memory, through usual pointer dereference, kernel translates it to a file operation. Essentially writing to memory becomes writing into a file. It is just a more fancy way of calling write().
Memory-mapped I/O lets us map a file on disk into a buffer in memory so that, when we fetch bytes from the buffer, the corresponding bytes of the file are read. Similarly, when we store data in the buffer, the corresponding bytes are automatically written to the file. This lets us perform I/O without using read or write.
(sidenote) I think first is called "IO mapped memory" and second is called "memory mapped IO". No wonder you are confused.
These appear in process maps as “drm mm object” or “i915”. You can see this in /proc/<pid>/maps
; given the PID of a process using GEM/DRM:
awk '/(drm mm object)|i915/ { hypidx = index($1, "-"); from = substr($1, 1, hypidx - 1); to = substr($1, hypidx + 1); sum += strtonum("0x" to) - strtonum("0x" from) } END { print sum }' /proc/${PID}/maps
will show the total size of the allocated GEM buffers. Calculating the total can be done by feeding in all maps which contain at least one occurrence of “drm mm object” or “i915”; as root:
find /proc -maxdepth 2 -name maps |
xargs grep -E -l "(drm mm object)|i915" |
xargs awk '/(drm mm object)|i915/ { hypidx = index($1, "-"); sum += strtonum("0x" substr($1, hypidx + 1)) - strtonum("0x" substr($1, 1, hypidx - 1)) } END { print sum }'
(-maxdepth 2
is necessary to avoid looking at thread maps). Some additional inode-based de-duplication might be necessary.
Best Answer
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 directly (although you can try to avoid it using
mincore
etc.)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)