Linux 进程的地址空间

Linux 进程的地址空间

2024 南京大学《操作系统:设计与实现》
Linux 进程的地址空间

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

进程的状态机模型

  • 进程状态 = 内存 + 寄存器
  • 到底什么是 “进程的内存”

1. 以下程序的 (可能) 输出是什么?

printf("%p\n", main);

2. 何种指针访问不会引发 segmentation fault?

char *p = random();
*p;  // Load
*p = 1; // Store
2024 南京大学《操作系统:设计与实现》
Linux 进程的地址空间

怎样查看 Linux 进程的地址空间?

center

(好奇 pmap 是如何实现的?)
2024 南京大学《操作系统:设计与实现》
Linux 进程的地址空间

进程的地址空间

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

  • 进程地址空间中的每一段
    • 地址 (范围) 和权限 (rwxsp)
    • 对应的文件: offset, dev, inode, pathname
      • TFM 里有更详细的解释
    • 和 readelf (-l) 里的信息互相验证

更多的提问:我们能 “控制” pmap 的输出吗?

  • 修改堆 (bss) 内存的大小
  • 在栈上分配大数组……
2024 南京大学《操作系统:设计与实现》
Linux 进程的地址空间

我们发现的宝藏

无需陷入内核的系统调用

  • 例子: time (2) 秒级时间和 gettimeofday (2) (非常聪明的实现)
  • 计算机系统里没有魔法!我们理解了进程地址空间的全部

center

2024 南京大学《操作系统:设计与实现》
Linux 进程的地址空间

管理进程地址空间

状态机的视角

  • 地址空间 = 带访问权限的内存段
    • 不存在 (不可访问)
    • 不存在 (可读/写/执行)
  • 管理 = 增加/删除/修改一段可访问的内存

你会提供怎样的系统调用?

2024 南京大学《操作系统:设计与实现》
Linux 进程的地址空间

Memory Map 系统调用

在状态机状态上增加/删除/修改一段可访问的内存

  • MAP_ANONYMOUS: 匿名 (申请) 内存
  • fd: 把文件 “搬到” 进程地址空间中 (例子:加载器)
  • 更多的行为请参考手册 (复杂性暴增)
// 映射
void *mmap(void *addr, size_t length, int prot, int flags,
           int fd, off_t offset);
int munmap(void *addr, size_t length);

// 修改映射权限
int mprotect(void *addr, size_t length, int prot);
2024 南京大学《操作系统:设计与实现》
Linux 进程的地址空间

使用 mmap

Example 1: 申请大量内存空间

  • 瞬间完成内存分配
    • mmap/munmap 为 malloc/free 提供了机制
    • libc 的大 malloc 会直接调用一次 mmap 实现
  • 不妨 strace/gdb 看一下

Example 2: Everything is a file

  • 映射大文件、只访问其中的一小部分
with open('/dev/sda', 'rb') as fp:
    mm = mmap.mmap(fp.fileno(),
                   prot=mmap.PROT_READ, length=128 << 30)
    hexdump.hexdump(mm[:512])
2024 南京大学《操作系统:设计与实现》