# 第 13 章实验:你看到的每个地址都是虚拟的 ## 做什么 - `va.c`:原书 13 章 ASIDE 的程序,打印代码(main)、堆(malloc 返回值)、栈(局部变量)的地址。 - `va2.c`:按从低到高列出代码、数据、bss、小块 malloc(brk 堆)、大块 malloc(mmap)、栈的地址。 - `va-fork.c`:fork 后父子进程打印同一个变量的地址和值:地址相同、值不同。 - `memory-user.c`:原书作业第 3 题,占用指定 MB 内存并反复访问,配合 `free -m`、`pmap -x` 观察。 ## 怎么跑 ``` make ./va; ./va # 两次地址不同:ASLR(地址空间布局随机化) setarch $(uname -m) -R ./va # 关闭 ASLR:每次(每个进程)地址相同 ./va2 ./va-fork ./memory-user 1000 5 & free -m # used 大约增加 1000MB ./memory-user 50 20 & pmap -x $! make run # 依次运行以上大部分命令 ``` ## 该观察到什么、为什么 - 打印出来的地址都是虚拟地址;关闭 ASLR 后两个进程的地址完全相同,互不冲突,因为每个进程有私有地址空间。 - `va-fork`:子进程把 x 改成 200,父进程仍看到 100——同一个虚拟地址被翻译到了不同的物理内存。 - `malloc(100e6)` 这种大块请求 glibc 用 mmap 分配,所以"堆"地址落在高处的共享库附近;小块 malloc 在紧跟数据段的 brk 堆里。 - `pmap` 显示现代地址空间远不止"代码/堆/栈":可执行文件的多个段、共享库、匿名映射、栈、vdso 等。