Operating Systems — Lecture 03
$ ps -e -o pid,comm,rss --sort -rss | head -3
PID COMMAND RSS
33283 chrome 1657396 1.6 GB, one process of dozens
$ time ./row 0.05 s same instructions,
$ time ./column 0.46 s nine times slower
$ valgrind --leak-check=full ./task
39,556 bytes in 4,000 blocks are definitely lost
Functionality · correctness · security · performance · efficiency.
An address is the index. A pointer is a variable holding one.
| size | a byte takes | |
|---|---|---|
| cache | KB–MB | nanoseconds |
| memory | GB | ~100 ns |
| disk | TB | µs–ms |
The cache hides memory from the CPU; the buffer cache hides the disk from programs.
An area = start + size. Allocate: new area, or extend one. Free: remove, or shrink.
$ ./basic
----- Allocate memory -----
----- Write to memory -----
----- Read from memory -----
----- Execute memory -----
Segmentation fault (core dumped) SEGV_ACCERR, in the heap, rw-
Every area has permissions. The hardware checks them. There is no third option.
pmap, line by line$ pmap -x $(pidof see-pmap-static)
0000000000400000 4 r---- see-pmap-static ELF header
0000000000401000 564 r-x-- see-pmap-static .text (libc inside)
000000000048e000 172 r---- see-pmap-static .rodata
00000000004be000 24 rw--- see-pmap-static .data
00000000004c4000 40 rw--- [ anon ] .bss
0000000034c5d000 136 rw--- [ anon ] heap
00007ffd49694000 136 rw--- [ stack ] stack
Static: from the file, fixed. Dynamic: made at run time, zero-filled, resizable.
$ size see-pmap-static
text data bss .bss: 38 KB in memory, 0 bytes in the file
749834 41848 39016
$ ./allocation-types
ro_data: 0x402020 .rodata the linker, before the run
init_data: 0x408080 .data
local_scope_data: 0x4080a0 .data static local: load time, not "global"
non_init_data: 0x40c0e0 .bss
heap_data: 0x316932c0 heap malloc(), at run time
stack_buffer: 0x7ffd4f5633f0 stack the call, at run time
mapped_data: 0x7c51ef5c0000 mapping mmap(), at run time
nm allocation-types already knows the first four.
[ stack ] 136 KB -> 420 KB 100 calls deep; the kernel extended it on a fault
heap 132 KB -> 268 KB 4 x malloc(64 KB)
268 KB -> 140 KB 4 x free()
mapping + 64 KB mmap(), then munmap()
malloc()malloc()s$ strace -e trace=brk,mmap ./malloc_kb 100 # 10 x 100 KB
brk(0x62161b3d6000) brk(0x62161b408000) brk(0x62161b43a000)
brk(0x62161b46c000) brk(0x62161b49e000) brk(0x62161b4d0000)
brk(0x62161b4b7000) <- free(): the heap shrinks
$ strace -e trace=brk,mmap ./malloc_kb 1000 # 10 x 1000 KB
mmap(NULL, 1028096, ...) = 0x765b4323e000 x 10
munmap(0x765b4272d000, 1028096)
Six crossings for ten requests; or one each, when the block is worth it.
A process sees its memory as a list of areas.
Static ones are built from the file before main(); dynamic ones grow while it runs — the stack by itself, the heap and mappings through an allocator, over brk() and mmap().
Everything is an address into one of them. Anything else is a fault.