Memory Byte
address stored
999 128
998 255
997 254
996 128
· ·
· ·
· ·
3 2
2 0
1 104
0 77
•
400
┌─399─┐
│ 398 │
│ 397 │
│ • │
│ • │ Page 3
│ • │
│ 302 │
│ 301 │
└─300─┘
299
•
┌─────┐
│ CPU │
└─────┘
↕
┌────────────┐
│ Page Table │
└────────────┘
↕
┌─────┐
│ RAM │
└─────┘
Virtual Physical
┌──────────────┐
│ 9-- → 59-- │
│ 8-- → 63-- │
│ 7-- → - │
│ 6-- → 61-- │
│ 5-- → 60-- │
│ 4-- → - │
│ 3-- → - │
│ 2-- → - │
│ 1-- → 36-- │
│ 0-- → 35-- │
└──────────────┘
“Read byte 821” ⇒ “Read byte 6321”
┌──────────────┐
│ 9-- → 59-- │
→ │ 8-- → 63-- │ ←
│ 7-- → - │
│ 6-- → 61-- │
│ 5-- → 60-- │
│ 4-- → - │
│ 3-- → - │
│ 2-- → - │
│ 1-- → 36-- │
│ 0-- → 35-- │
└──────────────┘
“Read byte 190” ⇒ “Read byte 3690”
┌──────────────┐
│ 9-- → 59-- │
│ 8-- → 63-- │
│ 7-- → - │
│ 6-- → 61-- │
│ 5-- → 60-- │
│ 4-- → - │
│ 3-- → - │
│ 2-- → - │
→ │ 1-- → 36-- │ ←
│ 0-- → 35-- │
└──────────────┘
“Write byte 522” ⇒ “Write byte 6022”
┌──────────────┐
│ 9-- → 59-- │
│ 8-- → 63-- │
│ 7-- → - │
│ 6-- → 61-- │
→ │ 5-- → 60-- │ ←
│ 4-- → - │
│ 3-- → - │
│ 2-- → - │
│ 1-- → 36-- │
│ 0-- → 35-- │
└──────────────┘
“Read byte 700” ⇒ Page fault
┌──────────────┐
│ 9-- → 59-- │
│ 8-- → 63-- │
→ │ 7-- → - │ ←
│ 6-- → 61-- │
│ 5-- → 60-- │
│ 4-- → - │
│ 3-- → - │
│ 2-- → - │
│ 1-- → 36-- │
│ 0-- → 35-- │
└──────────────┘
Everything your program needs
You say: “Run my editor!”
┌──────────────┐
│ 9-- → - │
│ 8-- → - │
│ 7-- → - │
│ 6-- → - │
│ 5-- → - │
│ 4-- → - │
│ 3-- → - │
│ 2-- → - │
│ 1-- → 36-- │ libcurses
│ 0-- → 35-- │ editor “binary” (program)
└──────────────┘
┌──────────────┐
│ 9-- → 59-- │ stack (“bottom” = oldest)
│ 8-- → 63-- │ stack (“top” = newest)
│ 7-- → - │
│ 6-- → - │
│ 5-- → - │
│ 4-- → - │
│ 3-- → - │
│ 2-- → - │
│ 1-- → 36-- │ libcurses
│ 0-- → 35-- │ editor “binary” (program)
└──────────────┘
┌──────────────┐
│ 9-- → 59-- │ stack (“bottom” = oldest)
│ 8-- → 63-- │ stack (“top” = newest)
│ 7-- → - │
│ 6-- → 61-- │ heap (file being edited)
│ 5-- → 60-- │ heap (settings)
│ 4-- → - │
│ 3-- → - │
│ 2-- → - │
│ 1-- → 36-- │ libcurses
│ 0-- → 35-- │ editor “binary” (program)
└──────────────┘
Processes can't see each other's pages
Processes can't see OS pages
The OS wipes reallocated pages with 0s
Processes can't overwrite each other
Processes can't crash the OS
┌────────────────┐
│ 9-- → 59-- w │ stack
│ 8-- → 63-- w │ stack
│ 7-- → - │
│ 6-- → 61-- w │ heap
│ 5-- → 60-- w │ heap
│ 4-- → - │
│ 3-- → - │
│ 2-- → - │
│ 1-- → 36-- r │ libcurses
│ 0-- → 35-- r │ binary
└────────────────┘
“Read from 331”
┌────────────────┐
│ 9-- → 59-- w │
│ 8-- → 63-- w │
│ 7-- → - │
│ 6-- → 61-- w │
│ 5-- → 60-- w │
│ 4-- → - │
→ │ 3-- → - │ → SEGMENTATION FAULT
│ 2-- → - │
│ 1-- → 36-- r │
│ 0-- → 35-- r │
└────────────────┘
“Write to 101”
┌────────────────┐
│ 9-- → 59-- w │
│ 8-- → 63-- w │
│ 7-- → - │
│ 6-- → 61-- w │
│ 5-- → 60-- w │
│ 4-- → - │
│ 3-- → - │
│ 2-- → - │
→ │ 1-- → 36-- r │ → SEGMENTATION FAULT
│ 0-- → 35-- r │
└────────────────┘
Sharing!
┌────────────────┐ ┌────────────────┐
│ 9-- → 59-- w │ stack │ 9-- → 48-- w │ stack
│ 8-- → 63-- w │ stack │ 8-- → - │
│ 7-- → - │ │ 7-- → 51-- w │ heap
│ 6-- → 61-- w │ heap │ 6-- → 50-- w │ heap
│ 5-- → 60-- w │ heap │ 5-- → 46-- w │ heap
│ 4-- → - │ │ 4-- → - │
│ 3-- → - │ │ 3-- → 39-- r │ libjson
│ 2-- → 39-- r │ libjson │ 2-- → 48-- r │ libX11
│ 1-- → 36-- r │ libc │ 1-- → 36-- r │ libc
│ 0-- → 35-- r │ python │ 0-- → 47-- r │ firefox
└────────────────┘ └────────────────┘
┌────────────────┐ ┌────────────────┐
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ 3-- → 39-- r │ libjson
│ 2-- → 39-- r │ libjson │ │
│ 1-- → 36-- r │ libc │ 1-- → 36-- r │ libc
│ │ │ │
└────────────────┘ └────────────────┘
┌────────────────┐ ┌────────────────┐
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ 3-- → 39-- r │ libjson
│ 2-- → 39-- r │ libjson │ │
│ 1-- → 36-- r │ libc │ 1-- → 36-- r │ libc
│ │ │ │
└────────────────┘ └────────────────┘
┌────────────────┐ ┌────────────────┐
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ 3-- → 39-- r │ libjson
│ 2-- → 39-- r │ libjson │ │
│ 1-- → 36-- r │ libc │ 1-- → 36-- r │ libc
│ │ │ │
└────────────────┘ └────────────────┘
(A's memory use) + (B's memory use)
Δ memory
┌────────────────┐
│ 9-- → 59-- w │ stack
│ 8-- → - │
│ 7-- → - │
│ 6-- → - │
│ 5-- → - │
│ 4-- → - │
│ 3-- → - │
│ 2-- → - │
│ 1-- → 36-- r │ libc
│ 0-- → 35-- r │ python
└────────────────┘
┌────────────────┐
│ 9-- → 59-- w │ stack
│ 8-- → - │
│ 7-- → - │
│ 6-- → - │
│ 5-- → 60-- w │ foo.py ←
│ 4-- → - │
│ 3-- → - │
│ 2-- → - │
│ 1-- → 36-- r │ libc
│ 0-- → 35-- r │ python
└────────────────┘
┌────────────────┐
│ 9-- → 59-- w │ stack
│ 8-- → - │
│ 7-- → - │
│ 6-- → 61-- w │ codeobj ←
│ 5-- → 60-- w │ foo.py
│ 4-- → - │
│ 3-- → - │
│ 2-- → - │
│ 1-- → 36-- r │ libc
│ 0-- → 35-- r │ python
└────────────────┘
┌────────────────┐
│ 9-- → 59-- w │ stack
│ 8-- → - │
│ 7-- → 63-- w │ data ←
│ 6-- → 61-- w │ codeobj
│ 5-- → 60-- w │ foo.py
│ 4-- → - │
│ 3-- → - │
│ 2-- → - │
│ 1-- → 36-- r │ libc
│ 0-- → 35-- r │ python
└────────────────┘
┌────────────────┐
│ 9-- → 59-- w │ stack
│ 8-- → - │
│ 7-- → 63-- w │ data ←
│ 6-- → 61-- w │ codeobj
│ 5-- → 60-- w │ foo.py
│ 4-- → - │
│ 3-- → - │
│ 2-- → - │
│ 1-- → 36-- r │ libc
│ 0-- → 35-- r │ python
└────────────────┘
┌────────────────┐ ┌────────────────┐
│ 9-- → 59-- w │ ≠ │ 9-- → 48-- w │ stack
│ 8-- → - │ │ 8-- → - │
│ 7-- → 63-- w │ ≠ │ 7-- → 71-- w │ data
│ 6-- → 61-- w │ ≠ │ 6-- → 69-- w │ codeobj
│ 5-- → 60-- w │ ≠ │ 5-- → 62-- w │ foo.py
│ 4-- → - │ │ 4-- → - │
│ 3-- → - │ │ 3-- → - │
│ 2-- → - │ │ 2-- → - │
│ 1-- → 36-- r │ │ 1-- → 36-- r │ libc
│ 0-- → 35-- r │ │ 0-- → 35-- r │ python
└────────────────┘ └────────────────┘
Q: Why not share code objects?
Q: Why not make them read-only?
A: Reference Counts
What does this code do?
f(5)
f(5)
Now, another basic concept—
┌────────────────┐
│ 9-- → 59-- w │ stack
│ 8-- → 63-- w │ stack
│ 7-- → - │
│ 6-- → 61-- w │ heap
│ 5-- → 60-- w │ heap
│ 4-- → - │
│ 3-- → - │
│ 2-- → 39-- r │ libjson
│ 1-- → 36-- r │ libc.so
│ 0-- → 35-- r │ python
└────────────────┘
┌────────────────┐
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ 1-- → 36-- r │ libc.so
│ 0-- → 35-- r │ python
└────────────────┘
┌────────────────┐
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ 1-- → 36-- r │ libc.so
│ 0-- → 35-- r │ python
└────────────────┘
prog.c → prog
But then prog.c got really big
“compile” “link”
cmdn.c → cmdn.o ↘
opts.c → opts.o → prog
slen.c → slen.o ↗
“compile” “link”
cmdn.c → cmdn.o ↘
opts.c → opts.o → prog
slen.c → slen.o ↗
$ nm p_move.o
U _nc_panelhook
U is_linetouched
00000000 T move_panel
U mvwin
U wtouchln
$ ld -o prog foo.o bar.o baz.o
foo.o: In function `main':
foo.c:(.text+0x7): undefined reference to `haute'
collect2: ld returned 1 exit status
$ ar t /usr/lib/libpanel.a
panel.o
p_above.o
p_below.o
p_bottom.o
p_delete.o
p_hide.o
p_hidden.o
p_move.o
p_new.o
p_replace.o
p_show.o
p_top.o
p_update.o
p_user.o
p_win.o
┌────────────────┐
│ . │
│ . │
│ . │
│ 1-- → 36-- r │ libc.so
│ 0-- → 35-- r │ python
└────────────────┘
┌────────────────┐
│ . │
│ . │
│ . │
│ 1-- → 36-- r │ libc.so
│ 0-- → 35-- r │ python
└────────────────┘
$ ldd /usr/bin/python2.7
linux-gate.so.1
libpthread.so.0
libdl.so.2
libutil.so.1
libssl.so.1.0.0
libcrypto.so.1.0.0
libz.so.1
libm.so.6
libc.so.6
/lib/ld-linux.so.2
$ nm -D /usr/bin/python2.7
.
.
.
U unlink
U unsetenv
U utime
U utimes
U wait
U wait3
U wait4
U waitpid
U wcscoll
U writ
$ ldd /usr/lib/pyshared/python2.7/lxml/etree.so
linux-gate.so.1
libxslt.so.1
libexslt.so.0
libxml2.so.2
libpthread.so.0
libc.so.6
libm.so.6
libgcrypt.so.11
libdl.so.2
libz.so.1
/lib/ld-linux.so.2
libgpg-error.so.0
/* libtiny.c */
helper() { return 42; }
gcc libtiny.c -shared -o libtiny.so
/* tinymodule.c */
#include <python2.7/Python.h>
static PyMethodDef TinyMethods[] = {
{NULL, NULL, 0, NULL}
};
PyMODINIT_FUNC inittiny(void)
{
helper(); /* the call into libtiny.so */
(void) Py_InitModule("tiny", TinyMethods);
}
$ export LD_LIBRARY_PATH=.
$ ldd tinymodule.so
linux-gate.so.1
libtiny.so
libc.so.6
/lib/ld-linux.so.2
$ python -c 'import tiny'
ImportError: ./tinymodule.so:
undefined symbol: helper
$ nm tinymodule.so
...
00000354 T _init
U helper
0000047c T inittiny
$ nm libtiny.so
...
000002f4 T _init
0000041c T another_helper
Files:
┌────────────────┐
│ 9-- → 59-- w │ stack
│ 8-- → - │
│ 7-- → - │
│ 6-- → 61-- w │ heap
│ 5-- → - │
│ 4-- → - │ (libc.so)
│ 3-- → - │ (libc.so)
│ 2-- → - │ (python)
│ 1-- → - │ (python)
│ 0-- → 35-- r │ python ← LOAD FROM DISK
└────────────────┘
┌────────────────┐
│ 9-- → 59-- w │ stack
│ 8-- → - │
│ 7-- → - │
│ 6-- → 61-- w │ heap
│ 5-- → - │
│ 4-- → - │ (libc.so)
│ 3-- → - │ (libc.so)
│ 2-- → 37-- r │ python ← LOAD FROM DISK
│ 1-- → - │ (python)
│ 0-- → 35-- r │ python
└────────────────┘
┌────────────────┐
│ 9-- → 59-- w │ stack
│ 8-- → - │
│ 7-- → - │
│ 6-- → 61-- w │ heap
│ 5-- → - │
│ 4-- → 41-- r │ libc.so ← LOAD FROM DISK
│ 3-- → - │ (libc.so)
│ 2-- → 37-- r │ python
│ 1-- → - │ (python)
│ 0-- → 35-- r │ python
└────────────────┘
┌────────────────┐
│ 9-- → 59-- w │ stack
│ 8-- → - │
│ 7-- → - │
│ 6-- → 61-- w │ heap
│ 5-- → - │
│ 4-- → 41-- r │ libc.so
│ 3-- → - │ (libc.so)
│ 2-- → 37-- r │ python
│ 1-- → - │ (python)
│ 0-- → 35-- r │ python
└────────────────┘
┌────────────────┐
│ 9-- → 59-- w │ stack
│ 8-- → - │
│ 7-- → - │
│ 6-- → - │
│ 5-- → - │
│ 4-- → 61-- w │ heap
│ 3-- → - │
│ 2-- → 41-- r │ libc.so
│ 1-- → - │ (python)
│ 0-- → 35-- r │ python
└────────────────┘
┌────────────────┐
│ 9-- → 59-- w │ stack
│ 8-- → - │
│ 7-- → - │ (heap)
│ 6-- → - │ (heap)
│ 5-- → - │ (heap)
│ 4-- → 61-- w │ heap
│ 3-- → - │
│ 2-- → 41-- r │ libc.so
│ 1-- → - │ (python)
│ 0-- → 35-- r │ python
└────────────────┘
┌────────────────┐
│ 9-- → 59-- w │ stack
│ 8-- → - │
│ 7-- → - │ (heap) ←
│ 6-- → - │ (heap) ←
│ 5-- → - │ (heap) ←
│ 4-- → 61-- w │ heap
│ 3-- → - │
│ 2-- → 41-- r │ libc.so
│ 1-- → - │ (python)
│ 0-- → 35-- r │ python
└────────────────┘
┌────────────────┐
│ 9-- → 59-- w │ stack
│ 8-- → - │
│ 7-- → - │ (heap) ←
│ 6-- → - │ (heap) ←
│ 5-- → - │ (heap) ←
│ 4-- → 61-- w │ heap
│ 3-- → - │
│ 2-- → 41-- r │ libc.so
│ 1-- → - │ (python)
│ 0-- → 35-- r │ python
└────────────────┘
┌────────────────┐
│ 9-- → 59-- w │ stack
│ 8-- → - │
│ 7-- → - │ (heap) ←
│ 6-- → - │ (heap) ←
│ 5-- → - │ (heap) ←
│ 4-- → 61-- w │ heap
│ 3-- → - │
│ 2-- → 41-- r │ libc.so
│ 1-- → - │ (python)
│ 0-- → 35-- r │ python
└────────────────┘
↓ ↓
PID USER VIRT RES SHR S %CPU %MEM COMMAND
1217 root 195m 94m 53m S 2 2.6 Xorg
7304 brandon 183m 45m 19m S 2 1.3 chromium
2027 brandon 531m 162m 37m S 1 4.5 chromium
2319 brandon 179m 58m 23m S 1 1.6 chromium
18841 brandon 2820 1188 864 R 1 0.0 top
9776 brandon 175m 49m 12m S 0 1.4 chromium
↑ ↑
┌────────────────┐ VIRT RES
│ 9-- → 59-- w │ stack ✓ ✓
│ 8-- → - │
│ 7-- → - │ (heap) ✓
│ 6-- → - │ (heap) ✓
│ 5-- → - │ (heap) ✓
│ 4-- → 61-- w │ heap ✓ ✓
│ 3-- → - │
│ 2-- → 41-- r │ libc.so ✓ ✓
│ 1-- → - │ (python) ✓
│ 0-- → 35-- r │ python ✓ ✓
└────────────────┘
↓
PID USER VIRT RES SHR S %CPU %MEM COMMAND
1217 root 195m 94m 53m S 2 2.6 Xorg
7304 brandon 183m 45m 19m S 2 1.3 chromium
2027 brandon 531m 162m 37m S 1 4.5 chromium
2319 brandon 179m 58m 23m S 1 1.6 chromium
18841 brandon 2820 1188 864 R 1 0.0 top
9776 brandon 175m 49m 12m S 0 1.4 chromium
↑
08048000-08238000 r-xp .../bin/python
Size: 1984 kB
Rss: 896 kB
b73b9000-b752f000 r-xp .../libc-2.13.so
Size: 1496 kB
Rss: 528 kB
bfc48000-bfc69000 rw-p [stack]
Size: 136 kB
Rss: 104 kB
08048000-08238000 r-xp .../bin/python
Size: 1984 kB
Rss: 896 kB
>>> frozenset()
08048000-08238000 r-xp .../bin/python
Size: 1984 kB
Rss: 916 kB
916 - 896 = 20 new kilobytes
$ python -c 'range(500000000)'
08048000-08238000 r-xp .../bin/python
Size: 1984 kB
Rss: 916 kB
08048000-08238000 r-xp .../bin/python
Size: 1984 kB
Rss: 464 kB
08048000-08238000 r-xp .../bin/python
Size: 1984 kB
Rss: 916 kB
08048000-08238000 r-xp .../bin/python
Size: 1984 kB
Rss: 464 kB
08048000-08238000 r-xp .../bin/python
Size: 1984 kB
Rss: 916 kB
08048000-08238000 r-xp .../bin/python
Size: 1984 kB
Rss: 464 kB
08048000-08238000 r-xp .../bin/python
Size: 1984 kB
Rss: 916 kB
08048000-08238000 r-xp .../bin/python
Size: 1984 kB
Rss: 464 kB
(well, there is one difference)
— Gustavo Duarte
And now, a Unix superpower!
A
↓
B
↓
C
↓
D
Process 1 A
↓
B
↓
C
↓
D — os.spawn() → A Process 2
↓ ↓
. B
. ↓
. C
↓ ↓
. D
Process 1 A
↓
B
↓
C
↓
D — os.fork() ↴ Process 2
↓ ↓
E E
↓ ↓
F F
↓ ↓
fork() parent fork() child
┌────────────────┐ ┌─────────────────┐
│ 9-- → 59-- w │ stack │ 9-- → new copy │
│ 8-- → 63-- w │ stack │ 8-- → new copy │
│ 7-- → - │ │ 7-- → - │
│ 6-- → 61-- w │ heap │ 6-- → new copy │
│ 5-- → 60-- w │ heap │ 5-- → new copy │
│ 4-- → - │ │ 4-- → - │
│ 3-- → - │ │ 3-- → - │
│ 2-- → 39-- r │ libjson │ 2-- → (same) │
│ 1-- → 36-- r │ libc │ 1-- → (same) │
│ 0-- → 35-- r │ python │ 0-- → (same) │
└────────────────┘ └─────────────────┘
fork() parent fork() child
┌────────────────┐ ┌────────────────┐
│ 9-- → 59-- r │ stack │ 9-- → 59-- r │
│ 8-- → 63-- r │ stack │ 8-- → 63-- r │
│ 7-- → - │ │ 7-- → - │
│ 6-- → 61-- r │ heap │ 6-- → 61-- r │
│ 5-- → 60-- r │ heap │ 5-- → 60-- r │
│ 4-- → - │ │ 4-- → - │
│ 3-- → - │ │ 3-- → - │
│ 2-- → 39-- r │ libjson │ 2-- → (same) │
│ 1-- → 36-- r │ libc │ 1-- → (same) │
│ 0-- → 35-- r │ python │ 0-- → (same) │
└────────────────┘ └────────────────┘
fork() parent fork() child
┌────────────────┐ ┌────────────────┐
│ 9-- → 59-- r │ stack │ 9-- → 59-- r │
→ │ 8-- → 63-- w │ ← stack → │ 8-- → 77-- w │ ←
│ 7-- → - │ │ 7-- → - │
│ 6-- → 61-- r │ heap │ 6-- → 61-- r │
│ 5-- → 60-- r │ heap │ 5-- → 60-- r │
│ 4-- → - │ │ 4-- → - │
│ 3-- → - │ │ 3-- → - │
│ 2-- → 39-- r │ libjson │ 2-- → (same) │
│ 1-- → 36-- r │ libc │ 1-- → (same) │
│ 0-- → 35-- r │ python │ 0-- → (same) │
└────────────────┘ └────────────────┘
# Create a list
biglist = ['foo']
for n in range(1, 8460000):
biglist.append(n) # ~100 MB
# put fork() here
# Iterate across the list
t0 = time.time()
all(n for n in biglist)
t1 = time.time()
$ cat /proc/22364/smaps | awk '/heap/,/Private_D/'
08d60000-0ef90000 rw-p 00000000 00:00 0 [heap]
Size: 100544 kB
Rss: 100544 kB
Pss: 50294 kB
Shared_Clean: 0 kB
Shared_Dirty: 100500 kB
Private_Clean: 0 kB
Private_Dirty: 44 kB
$ cat /proc/22364/smaps | awk '/heap/,/Private_D/'
08d60000-0ef90000 rw-p 00000000 00:00 0 [heap]
Size: 100544 kB
Rss: 100544 kB
Pss: 100274 kB
Shared_Clean: 0 kB
Shared_Dirty: 540 kB
Private_Clean: 0 kB
Private_Dirty: 100004 kB
At finish: 0.5% of heap shared
$ cat /proc/22385/smaps | awk '/heap/,/Private_D/'
0a5c9000-11fba000 rw-p 00000000 00:00 0 [heap]
Size: 124868 kB
Rss: 124540 kB
Pss: 62274 kB
Shared_Clean: 0 kB
Shared_Dirty: 124532 kB
Private_Clean: 0 kB
Private_Dirty: 8 kB
$ cat /proc/22385/smaps | awk '/heap/,/Private_D/'
0a5c9000-11fba000 rw-p 00000000 00:00 0 [heap]
Size: 124868 kB
Rss: 124868 kB
Pss: 63160 kB
Shared_Clean: 0 kB
Shared_Dirty: 123416 kB
Private_Clean: 0 kB
Private_Dirty: 1452 kB
At finish: 96.1% of heap shared
import threading
t = threading.Thread(target=myfunc)
t.start()
main thread child thread
┌────────────────┐ ┌────────────────┐
│ 9-- → 59-- r │ stack │ 9-- → 59-- r │
│ 8-- → 63-- w │ stack │ 8-- → 77-- w │
└────────────┬───┴─────────┴──┬─────────────┘
│ 7-- → - │
│ 6-- → 61-- w │ heap
│ 5-- → 60-- w │ heap
│ 4-- → - │
│ 3-- → - │
│ 2-- → 39-- r │ libjson
│ 1-- → 36-- r │ libc
│ 0-- → 35-- r │ python
└────────────────┘
import mmap, os
map = mmap.mmap(-1, 100)
os.fork()
...
fork() parent fork() child
┌────────────────┐ ┌────────────────┐
│ 9-- → 59-- r │ stack │ 9-- → 59-- r │
│ 8-- → 63-- w │ stack │ 8-- → 77-- w │
└─────────────┬──┴───────────┴─┬──────────────┘
│ 7-- → 88-- - │ mmap segment
┌─────────────┴──┬───────────┬─┴──────────────┐
│ 6-- → 61-- r │ heap │ 6-- → 61-- r │
│ 5-- → 60-- r │ heap │ 5-- → 60-- r │
│ 4-- → - │ │ 4-- → - │
│ 3-- → - │ │ 3-- → - │
│ 2-- → 39-- r │ libjson │ 2-- → (same) │
│ 1-- → 36-- r │ libc │ 1-- → (same) │
│ 0-- → 35-- r │ python │ 0-- → (same) │
└────────────────┘ └────────────────┘
┌────────────────┐
│ 9-- → 59-- w │ stack
│ 8-- → - │
│ 7-- → 91-- - │ mmap[1] ↔ myfile
│ 6-- → 90-- - │ mmap[0] ↔ myfile
│ 5-- → - │
│ 4-- → 61-- w │ heap
│ 3-- → - │
│ 2-- → 41-- r │ libc.so
│ 1-- → - │ (python)
│ 0-- → 35-- r │ python
└────────────────┘
So, there you have it