• Rainbow
    2019-05-28
    越来越看不懂了,有什么好办法吗?

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

     2
     17
  • why
    2019-05-22
    - 内存管理信息在 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(内核代码, 也采用直接映射)
    展开
    
     9
  • 有铭
    2019-05-17
    老师,之前你说过,内核态对于所有进程都是相同的,那时我就问过,这话的意思是不是说内核态内存在真实的物理内存里其实只有1份?

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

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

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

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

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

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

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

    
     2
  • tuyu
    2019-08-14
    看到这里, 我觉得我们不能太关注code问题, 应该多关注数据结构和数据结构的关系, 这样就有目标了

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

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

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

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

    作者回复: 可能是图有些误解,堆在High memory区域。图中指的是数据结构都保存在直接映射区。但是vmalloc分配出来是给内核用的。

    内核代码,全局变量,bss都是在代码段的。其他动态生成的变量都是在直接映射区的

    
     1
  • 一笔一画
    2019-05-17
    老师,请教下,64位布局里面,为什么会有这个8T空档?另外,32位上用户进程是优先使用高端内存吗?

    作者回复: 设计的时候就预留的呀。如果分配堆有高端内存是会优先使用的

    
     1
  • 淤白
    2020-01-29
    本篇文章看了几遍才勉强理解,离记忆还差些,但还是消除了心中的疑惑。

    通过本篇文章,主要了解的知识是:对于用户态的内存布局,32 位和 64 位并没有太大区别,记录着需要用到的类似数据结构;而对于内核态的内存布局,32 位的内存紧张,有一个 896 M 的直接映射区,其余的内存区域就比较小且紧凑,对于 64 位系统来说,内核态虚拟内存非常宽裕,所以分配起来会和 32 位的有区别。
    
    
  • yanger
    2020-01-25
    直接映射区前有8T空间,早就过了内核代码加载到物理内存的位置,没看懂,请问下什么意思
    
    
  • 烬默
    2019-12-17
    用户空间的mmap区域和其他地方不同呀,大部分都是写的由低到高,为什么这边是由高到低
    
    
  • Geek_54edc1
    2019-12-10
    32位的内核代码、数据、bss放到哪个区域呢?
    
    
  • 追风筝的人
    2019-11-23
    看不懂了
    
    
  • loser
    2019-11-08
    老师,程序运行中的变量值。是怎么被虚拟内存管理的?比如 int a=1。它是怎么知道写入到哪一个物理地址的
    
    
  • 柳长青
    2019-11-03
    老师,可不可以这样理解:即用户的虚拟内存和内核的虚拟内存在物理内存上并不是连续的,所以它们都可以在直接映射区(前896M)进行操作。
    
    
  • 耀明
    2019-10-22
    那两个图看不太懂,跟文字描述的有很大的不同。
    
    
  • kdb_reboot
    2019-10-02
    最后总结中的mmap和堆直接指到了物理内存,没看懂是什么意思,老师能解释一下吗?
     1
    
  • 张智凯
    2019-09-13
    请问 系统调用brk里用这样一段 if (do_brk(oldbrk, newbrk-oldbrk, &uf) < 0) ; goto out,如果do_brk返回小于0的值是分配堆内存失败了吗?do_brk会返回do_brk_flags的返回值,但是看do_brk_flags这个函数里只会返回0啊,是do_brk_flags没写全吗
    
    
我们在线,来聊聊吧