Linux 进程的地址空间

两个很基本 (但也很困难) 的问题

  • 以下程序的 (可能) 输出是什么?
printf("%p\n", main);

  • 何种指针访问不会引发 segmentation fault?
char *p = random();
*p; // 什么时候访问合法? 

这种小问题问 GPT 就好了

查看进程的地址空间

pmap (1) - report memory of a process

  • Claim: pmap 是通过访问 procfs (/proc/) 实现的
  • 如何验证这一点?

查看进程的地址空间

  • 等程序运行起来后 (gdb),使用 pmap 命令查看地址空间
  • 地址空间是若干连续的 “内存段”
    • “段” 的内存可以根据权限访问
    • 不在段内/违反权限的内存访问 触发 SIGSEGV

操作系统提供查看进程地址空间的机制

RTFM: /proc/[pid]/maps (man 5 proc)

  • 进程地址空间中的每一段
    • 地址 (范围) 和权限 (rwxsp)
    • 对应的文件: offset, dev, inode, pathname
      • TFM 里有更详细的解释
    • 和 readelf (-l) 里的信息互相验证
  • 好的本能:做一些代码上的调整,观察 address space 的变化
    • 堆 (bss) 内存的大小
    • 栈上的大数组 v.s. memory error
#define MB * 1048576
char mem[64 MB];

更完整的地址空间映象

0000555555554000 r--p     a.out
0000555555555000 r-xp     a.out
0000555555556000 r--p     a.out
0000555555557000 r--p     a.out
0000555555558000 rw-p     a.out
00007ffff7dc1000 r--p     libc-2.31.so
00007ffff7de3000 r-xp     libc-2.31.so
00007ffff7f5b000 r--p     libc-2.31.so
00007ffff7fa9000 r--p     libc-2.31.so
00007ffff7fad000 rw-p     libc-2.31.so
00007ffff7faf000 rw-p     (这是什么?)
00007ffff7fcb000 r--p     [vvar] (这又是什么?)
00007ffff7fce000 r-xp     [vdso] (这叒是什么?)
00007ffff7fcf000 r--p     (省略相似的 ld-2.31.so)
00007ffffffde000 rw-p     [stack]
ffffffffff600000 --xp     [vsyscall] (这叕是什么?)

RTFM (5 proc): 我们发现的宝藏

vdso (7): Virtual system calls: 只读的系统调用也许可以不陷入内核执行。

无需陷入内核的系统调用

  • 例子: time (2)
    • 时间:内核维护秒级的时间 (所有进程映射同一个页面)
  • 例子: gettimeofday (2)
    • RTFSC (非常聪明的实现)
  • 更多的例子:问 GPT 吧!
    • 计算机系统里没有魔法!我们理解了进程地址空间的全部