Memory-mapped file offset translation (source code)

= Memory-mapped file offset translation
{title2=$o=O+(v-B)$}

Let $P$ be the <memory page> size, $O$ the aligned starting <file offset>, $L$ the mapping length and $B$ its base <virtual address>. A valid displacement $r=v-B$ with $0\leq r<L$ corresponds to <file offset>
$$
o=O+r,\qquad j=\left\lfloor\frac{r}{P}\right\rfloor,\qquad d=r\bmod P.
$$
Here $j$ is the relative <memory page> index, the <floor function> selects its <integer> part, and <Euclidean division> gives the within-page displacement $d$. The backing page begins at $O+jP$. This identifies <file> contents; the <page table> separately selects a resident <page frame> and enforces permissions.

Take $P=4096$, $O=4096$ and $L=8192$ <bytes> in a <file> of at least 12288 <bytes>. A has a <shared file mapping> at $B_A=\mathtt{0x10000000}$. B has a <shared file mapping> at $B_B=\mathtt{0x20000000}$ and a <private file mapping> at $B_C=\mathtt{0x30000000}$. These bases are illustrative chosen results, not requested fixed addresses. All three mappings cover the same two backing pages: <file offsets> 4096–8191 and 8192–12287. Displacement $r=4133=4096+37$ selects relative page 1, within-page displacement 37 and <file offset> $o=8229=\mathtt{0x2025}$. Thus A's `0x10001025`, B's shared `0x20001025` and B's private `0x30001025` initially identify the same <byte>. The adjacent displacement 4134 identifies <file offset> 8230. Different <virtual addresses> can reach the same backing contents.

\Image[/memory-mapped-file-offset-page-mapping.png]
{title=Two <operating-system processes> map two backing pages at different <virtual addresses>; displacement 4133 identifies <file offset> 8229}

To access a requested <file offset> $q$ that is not aligned, choose $O=P\lfloor q/P\rfloor$ and displacement $q-O$. Mapping enough <bytes> to cover that displacement plus the requested length makes the desired data start inside the aligned mapping. Do not pass the unaligned $q$ directly as the <Linux kernel> `mmap` offset. For example, $q=8229$ uses $O=8192$ and displacement 37; that one-page start differs from our two-page mapping's $O=4096$.