趣谈 Linux 操作系统
刘超
前网易杭州研究院云计算技术部首席架构师
84364 人已学习
新⼈⾸单¥68
登录后,你可以任选4讲全文学习
课程目录
已完结/共 72 讲
趣谈 Linux 操作系统
15
15
1.0x
00:00/00:00
登录|注册

22 | 进程空间管理:项目组还可以自行布置会议室

上两节,我们讲了内存管理的三个方面,虚拟内存空间的管理、物理内存的管理以及内存映射。你现在对进程内存空间的整体布局应该有了一个大致的了解。今天我们就来详细看看第一个方面,进程的虚拟内存空间是如何管理的。
32 位系统和 64 位系统的内存布局有的地方相似,有的地方差别比较大,接下来介绍的时候,请你注意区分。好,我们现在正式开始!

用户态和内核态的划分

进程的虚拟地址空间,其实就是站在项目组的角度来看内存,所以我们就从 task_struct 出发来看。这里面有一个 struct mm_struct 结构来管理内存。
struct mm_struct *mm;
在 struct mm_struct 里面,有这样一个成员变量:
unsigned long task_size; /* size of task vm space */
我们之前讲过,整个虚拟内存空间要一分为二,一部分是用户态地址空间,一部分是内核态地址空间,那这两部分的分界线在哪里呢?这就要 task_size 来定义。
对于 32 位的系统,内核里面是这样定义 TASK_SIZE 的:
#ifdef CONFIG_X86_32
/*
* User space process size: 3GB (default).
*/
#define TASK_SIZE PAGE_OFFSET
#define TASK_SIZE_MAX TASK_SIZE
/*
config PAGE_OFFSET
hex
default 0xC0000000
depends on X86_32
*/
#else
/*
* User space process size. 47bits minus one guard page.
*/
#define TASK_SIZE_MAX ((1UL << 47) - PAGE_SIZE)
#define TASK_SIZE (test_thread_flag(TIF_ADDR32) ? \
IA32_PAGE_OFFSET : TASK_SIZE_MAX)
......
当执行一个新的进程的时候,会做以下的设置:
current->mm->task_size = TASK_SIZE;
对于 32 位系统,最大能够寻址 2^32=4G,其中用户态虚拟地址空间是 3G,内核态是 1G。
对于 64 位系统,虚拟地址只使用了 48 位。就像代码里面写的一样,1 左移了 47 位,就相当于 48 位地址空间一半的位置,0x0000800000000000,然后减去一个页,就是 0x00007FFFFFFFF000,共 128T。同样,内核空间也是 128T。内核空间和用户空间之间隔着很大的空隙,以此来进行隔离。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《趣谈 Linux 操作系统》
新⼈⾸单¥68
立即购买
登录 后留言

全部留言(55)

  • 最新
  • 精选
  • 有铭
    老师,之前你说过,内核态对于所有进程都是相同的,那时我就问过,这话的意思是不是说内核态内存在真实的物理内存里其实只有1份?

    作者回复: 是的,内核对于所有的进程,不但物理内存只有一份,虚拟内存也是只有一份。也就是说A进程用户态访问x虚拟地址和B进程用户态访问x虚拟地址是不同的虚拟地址,也即A进程用户态在x虚拟地址里面放了一个数值w,B进程用户态的x虚拟地址看不到w,对应的也是不同的物理地址。A进程内核态访问的y虚拟地址,和B进程内核态访问的y虚拟地址,是通一个虚拟地址,也对应相同的物理地址。也即A进程内核态在y虚拟地址方一个数值n,B进程的内核态如果能够访问y虚拟地址的话,也能看到n

    6
    52
  • Rainbow
    越来越看不懂了,有什么好办法吗?

    作者回复: 多看几遍哈,重点关注机制和流程

    8
    42
  • tuyu
    看到这里, 我觉得我们不能太关注code问题, 应该多关注数据结构和数据结构的关系, 这样就有目标了

    作者回复: 是的,重点关注数据结构和流程,代码作为参考

    9
  • G.S.K
    老师好,vm_area_struct描述内存区域,内存区域有text,data,bss,堆,mmap映射,栈区域,一个进程的vm_area_struct个数只有这6个吗?

    作者回复: 不是的,堆就不一定连续

    6
    9
  • Geek_49fbe5
    老师,如果一台X86的物理机的内存只有1G,那是不是意味着这台机子装不了linux操作系统呢,因为内核就得用1G的内存?

    作者回复: 要区分虚拟地址空间和物理地址空间,可以虚拟的大,物理的小

    2
    6
  • 幸运的🐴
    刘老师,为什么内核在load用户空间的内存映射到物理页的时候要自己在内核的持久映射区也建议一个映射呢,不能使用用户空间的映射吗?这样的话,持久映射区会不会有空间不够的情况?因为这块的虚拟空间很小(<1G),如果我mmap一个很大的文件到用户空间,那很明显没办法把这个文件映射到内核的虚拟空间来呀,这块它是怎么做的呢?另外,这个过程跟load elf不是类似的么?对于用户空间的进程的代码区,数据区等,还是需要把磁盘上的页读进内存吧?这个过程也需要在内核先映射,读完之后再解除映射?

    作者回复: 在内核里面,得使用虚拟地址将内容读取到内存来。读一部分,映射一部分。load_elf_binary会最终调用do_mmap_pgoff,一样的

    3
    5
  • 小松松
    请问下,像slab、伙伴系统这些工具跟用户空间和内核空间的虚拟内存、物理内存有什么关系呢? 一直很迷惑,请老师解答下。

    作者回复: 伙伴系统是物理内存的分配,slub是划分为更小,但是都要变成虚拟地址才能被访问。

    4
  • book尾汁
    问个问题,假如我创建一个只有512M内存的32位的虚拟机,那岂不是所有的物理内存都是对应内核的直接映射区,用户态程序还怎么通过mmap申请内存?

    作者回复: 直接映射区是一个区域的名称,不代表直接映射的部分把整个区域都用完,如果用不完,mmap也是可以放在这个区域里面的,只不过不是直接映射的方式访问,就像客厅叫客厅,也可以摆个床睡觉

    3
  • 🍀吴昊
    我请问下最后两张图没有看明白 1 32位直接映射区为什么还保存了堆信息?不是存在vmalloc来直接分配内存的嘛? 2 64位512M 用于存放内核代码段、全局变量、BSS 等。为什么图中却只映射到代码,而是由直接映射区去映射?

    作者回复: 可能是图有些误解,堆在High memory区域。图中指的是数据结构都保存在直接映射区。但是vmalloc分配出来是给内核用的。 内核代码,全局变量,bss都是在代码段的。其他动态生成的变量都是在直接映射区的

    3
  • 南瓜
    具体实现细节太多,这里一个指针、那里一个结构,是否应该更多考虑,这背后的思想,以及如何理解?毕竟不常接触这块儿,总不能去背诵。

    作者回复: 不要背诵,如果对着总结图能说出大概原理就可以啦

    2
收起评论
显示
设置
留言
55
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部