【操作系统】进程空间管理

用户态与内核态的划分

  • 进程的虚拟地址空间,就是换了个角度看内存。
  • 整个虚拟内存要一分为二, 一部分是内存态地址空间,一部分是内核态的内存空间
  • 32位系统,最大寻址是2^32 = 4G,其中用户态虚拟地址空间是3G, 内核态是1G。
  • 64位系统,虚拟地址只使用了 48位, 1 >> 47 相当于 47 ^2 ,也就是内核态和用户态各自拥有128T.
    在这里插入图片描述

用户态的布局

unsigned long mmap_base;	/* base of mmap area */
unsigned long total_vm;		/* total_vm 是总共映射的页的数目 */
unsigned long locked_vm;	/* Pages that have PG_mlocked set */
unsigned long pinned_vm;	/* Refcount permanently increased */
unsigned long data_vm;		/* VM_WRITE & ~VM_SHARED & ~VM_STACK */
unsigned long exec_vm;		/* VM_EXEC & ~VM_WRITE & ~VM_STACK */
unsigned long stack_vm;		/* VM_STACK */
unsigned long start_code, end_code, start_data, end_data;
unsigned long start_brk, brk, start_stack;
unsigned long arg_start, arg_end, env_start, env_end;
  • total_vm 是总共映射的页的数目,内存吃紧的时候,locked_vm 就是被锁定不能换出,pinned_vm 是不能换出,也不能移动。 换出 : 把内存写到硬盘

  • data_vm 是存放数据的页的数目,exec_vm 是存放可执行文件的页的数目,stack_vm 是栈所占的页的数目。

  • start_code 和 end_code 表示可执行代码的开始和结束位置,start_data 和 end_data 表示已初始化数据的开始位置和结束位置。

  • start_brk 是堆的起始位置,brk 是堆当前的结束位置。前面咱们讲过 malloc 申请一小块内存的话,就是通过改变 brk 位置实现的。

  • start_stack 是栈的起始位置,栈的结束位置在寄存器的栈顶指针中。

  • arg_start 和 arg_end 是参数列表的位置, env_start 和 env_end 是环境变量的位置。它们都位于栈中最高地址的地方

  • mmap_base 表示虚拟地址空间中用于内存映射的起始地址。这个空间是从高地址到低地址增长的。
    在这里插入图片描述

  • 这里用红黑树,就是为了快速查找一个内存区域,并在需要改变的时候,能够快速修改

  • anoy 就是 anonymous,匿名的意思,映射到文件就需要有 vm_file 指定被映射的文件。

  • 当 exec 运行一个二进制程序的时候,除了解析 ELF 的格式之外,另外一个重要的事情就是建立内存映射。
    在这里插入图片描述

  • 内存映射图 :
    在这里插入图片描述

  • 下面这俩种情况都会修改上面的映射关系

  • 第一种情况是函数的调用,涉及函数栈的改变,主要是改变栈顶指针。

  • 第二种情况是通过 malloc 申请一个堆内的空间,当然底层要么执行 brk,要么执行 mmap。关于内存映射的部分。

  • brk (堆) : 堆是从低地址向高地址增长的, 会有新旧的brk堆顶地址, 需要比较,如果俩者相同的话,则说明在同一页,则修改堆顶地址就行,指向新的地址, 如果新的 < 旧的 则说明不在一页,至少需要释放一页。

    • brk 判断是否需要分配新页, 并做对应操作; 需要分配新页时需要判断能否与其他 vm_area_struct 合并

内核态的布局

32 位
在这里插入图片描述
64位
在这里插入图片描述

小结

  • 内存管理信息在 task_struct 的 mm_struct 中
  • task_size 指定用户态虚拟地址大小
    • 32 位系统:3G 用户态, 1G 内核态
    • 64 位系统(只利用 48 bit 地址): 128T 用户态; 128T 内核态
  • 用户态地址空间布局和管理
    • mm_struct 中有映射页的统计信息(总页数, 锁定页数, 数据/代码/栈映射页数等)以及各区域地址
    • 有 vm_area_struct 描述各个区域(代码/数据/栈等)的属性(包含起始/终止地址, 可做的操作等), 通过链表和红黑树管理
    • 在 load_elf_bianry 时做 vm_area_struct 与各区域的映射, 并将 elf 映射到内存, 将依赖 so 添加到内存映射
    • 在函数调用时会修改栈顶指针; malloc 分配内存时会修改对应的区域信息(调用 brk 堆; 或调用 mmap 内存映射)
    • brk 判断是否需要分配新页, 并做对应操作; 需要分配新页时需要判断能否与其他 vm_area_struct 合并
  • 内核地址空间布局和管理
    • 所有进程看到的内核虚拟地址空间是同一个
    • 32 位系统, 前 896MB 为直接映射区(虚拟地址 - 3G = 物理地址)
      • 直接映射区也需要建立页表, 通过虚拟地址访问(除了内存管理模块)
      • 直接映射区组成: 1MB 启动时占用; 然后是内核代码/全局变量/BSS等,即 内核 ELF文件内容; 进程 task_struct 即内核栈也在其中
      • 896MB 也称为高端内存(指物理内存)
      • 剩余虚拟空间组成: 8MB 空余; 内核动态映射空间(动态分配内存, 映射放在内核页表中); 持久内存映射(储存物理页信息); 固定内存映射; 临时内存映射(例如为进程映射文件时使用)
    • 64 位系统: 8T 空余; 64T 直接映射区域; 32T(动态映射); 1T(物理页描述结构 struct page); 512MB(内核代码, 也采用直接映射)
      32位
      在这里插入图片描述
      64位
      在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CPT1024

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值