Linux内存管理
搜索与算法-引擎开发组-子嘉
大纲
 概念介绍
 处理器内存模型
 Linux系统内存管理
 高级内存管理
 程序开发注意事项
 未来发展趋势
第一章

概念介绍
  --物理,线性,逻辑地址
  --虚存
  --SWAP
  --MMU
  --TLB
  --CACHE
  --寻址过程
概念介绍
 物理、线性、逻辑地址
  – 物理地址 physical address
     • 用于在内存单元(memory cell)中寻址,该地址与内存的针脚
       (pin)相对应
     • 256M,512M,1G,2G,4G,16G,24G,32G
  – 逻辑地址 logical address
     • 机器指令中包含的寻址模式,如存取操作数 mov ax, ds:offset
     • X86的分段寻址模式
  – 线性地址 linear address
     • 处理器位数相关
     • 32,64,128位
概念介绍
 虚存(virtual memory)
  – 定义
     • 把内存与外存有机的结合起来使用,从而得到一个容量很大的
       “内存”,这是虚拟内存。进程不完全载入,就叫虚存。可以分
       成按需取页和按需取段两种方式
     • 程序员不考虑实际内存大小,将整个线性地址空间作为自己看
       到的内存,利用磁盘作为内存后援
  – 特点
     • 看到的内存空间是整个线性空间,大小是2⁶⁴
     • 物理内存不够就存磁盘
     • 程序不必完全载入
  – 本质 = 吹牛
概念介绍
 MMU (memory management unit) –内存管理单元
  – 作用
    • 将虚拟地址转换为内存实际的物理地址
    • 产生缺页中断 paging fault
    • 涉及寄存器:GDT LDT CR0 CR3 CS DS ES FS
概念介绍
 寻址过程
  – Phase1 根据cs寄存器中的segment selector获取segment
    descriptor
     • Segment selector 选择符,存的是索引

         Index 13-bit   TI table indictor 1-bit   RPL privilege level 2-bit

     • Segment descriptor 描述符,存的是段基址
概念介绍
 寻址过程
  – Phase1 根据cs寄存器中的segment selector获取segment
    descriptor
概念介绍
 寻址过程
  – Phase2根据segment descriptor和偏移获取线性地址
概念介绍
 寻址过程
  – Phase3根据线性地址获取物理地址
概念介绍
 TLB(Translation Lookaside Buffer) –并行翻译缓冲区
   – 作用
       •   存放线性地址到物理地址的映射
       •   加快线性地址到物理地址的翻译速度
       •   减少对内存的大量访问
       •   TLB以页还是具体的地址为单位呢?

                  Translation
Linear address                          physical address
                           miss

                     TLB
                                  hit
概念介绍
 cache
   – Why?
      • 快设备与慢设备的gap
      • 时间本地性,空间本地性
      • 一切皆cache

                 Proc/Regs
                 L1-Cache
  Biggerr        L2-Cache         Faster
                  Memory
               Disk, Tape, etc.
概念介绍
 cache
   – 作用
    • 缓存指令或者数据
    • 一级cache,二级cache


                                 更新
   物理地址                   miss
                 cache                memory


                    hit
概念介绍
 cache—directed mapped
                                  Block address
 31                                               9                    4               0
                Cache Tag       Example: 0x50     Cache Index          Byte Select
                                                      Ex: 0x01             Ex: 0x00
                         Stored as part
                         of the cache “state”

 Valid Bit   Cache Tag                                Cache Data
                                                  Byte 31          Byte 1     Byte 0   0




                                                              :
                         0x50                     Byte 63          Byte 33 Byte 32 1




                                                              :
                                                                                       2
                                                                                       3

      :                     :                                      :
                                                  Byte 1023                 Byte 992   31



                                                                   :
概念介绍

       Cache—N-way associative way
            – 例子:2-way组关联cache
                  • Index->set
                  • Compare tag
                                               Cache Index
Valid       Cache Tag        Cache Data                  Cache Data      Cache Tag   Valid
                             Cache Block 0             Cache Block 0

  :               :               :                             :           :         :


        Adr Tag
                  Compare             Sel1 1     Mux   0 Sel0          Compare

                                      OR
                                                    Cache Block
                                   Hit
概念介绍
 总流程


   逻辑地址        线性地址            物理地址            数据



                      Translatio
                                      memory
                          n
          段表


                         TLB          cache
概念介绍
 SWAP
   – 定义
    • 存放从物理内存中换出的内存页
  – 系统中的SWAP
    • Linux的swap分区
    • Windows的虚拟地址
第二章

处理器内存模型
  --乱序执行
  --内存操作与依赖类型
  --X86
处理器内存模型
 乱序执行 out of order
  – 定义
    • 将机器指令打散执行,非顺序执行
  – 优势
    • 一个clock可以执行更多的指令
    • 充分利用处理器
  – 例子
    • Read m1,eax
    • Read m2,ebx
    • Read m3,ecx
处理器内存模型
 内存操作与依赖类型
  – 操作类型
  • Read
  • write
 – 依赖类型
  •   Read after Read
  •   Read after Write
  •   Write after Read 在某些处理器上不属于hazard
  •   Write after Write
  •   Alias
  •   Write after non-relative write
处理器内存模型
 内存操作与依赖类型
  • R1 + R2 -> R3
  • R4 + R5 -> R6

  • 但是逻辑上是相关的
  • newnode->next = current;
  • Prev->next = newnode

  •   在某些处理器上要这么写(X86不必)
  •   newnode->next = current;
  •   Memory_Barrier()
  •   Prev->next = newnode
处理器内存模型
 X86 & SPARC
   – 强一致性的内存模型
 内存指令
  – sfence:在sfence指令前的写操作当必须在sfence指令后
    的写操作前完成。
  – lfence:在lfence指令前的读操作当必须在 lfence指令后
    的读操作前完成。
  – mfence:在mfence指令前的读写操作当必须在mfence
    指令后的读写操作前完成。
第三章

LINUX系统内存管理
  --MEMORY ZONE
  --BUDDY SYSTEM
  --系统自用内存管理SLAB
  --非连续内存VMALLOC
  --进程内存管理
  --PAGE CACHE
  --系统调用READ WRITE MMAP
  --页面替换算法PFRA
Linux系统内存管理
 Memory zone
  – 定义
     • 物理内存的一块区域
  – 分区原因
     • DMA只能访问0~16M的物理内存
     • 32位系统上,系统空间3G~4G,只能访问1G的物理内存
  – 分区
     •   ZONE_DMA 0~16M
     •   ZONE_NORMAL        16~896M
     •   ZONE_HIGHMEM       896M~
     •   No ZONE_HIGHMEM in 64 bit architecture
Linux系统内存管理
 Memory zone
  – 分布
     • 0-4K bios 4K-640K 各种卡 640K-16M 保留
     • 16M~896M 系统
Linux系统内存管理
 Buddy system
   – 定义
     • 分配单位是block 4096字节
     • 每个slot中的连续块个数相同。
       1,2,4,8,16,32,64,128,256,512,1024
     • 假设某个slot有b个块,空闲块的起始地址都能被 b*4096整除
  – 数据结构
     • Zone_mem_map
     • Free_area_t
     • bitmap
Linux系统内存管理
 Buddy system
Linux系统内存管理
 Buddy system
   – 分配allocate算法
     • Alloc_pages(zone, order)
     • 在zone中找到合适的块
     • 调用rmqueue来分配块
Linux系统内存管理
 Buddy system
   – 释放free算法
     • _ _free_pages_ok( page, order)
     • 如果需要做rebalanceing,直接将块插入到对应链表中
     • 正常的话,释放该块
  – 思考
     • Buddy以页为单位,如何处理小的申请?
     • 对于buddy的分配请求,来自谁?
     • 小物理内存申请来自谁?
Linux系统内存管理
 slab
   – 作用
    •   为内核频繁分配或者释放固定长度小内存
    •   区分内存访问,快者恒快,如process struct
    •   大小是2的幂,cache优化
    •   减少访问buddy的次数,防止cache flush
  – 实现
    • Cache(不是那个cache哦~) with type
    • Slab
    • Object
Linux系统内存管理
 slab
   – 图示
Linux系统内存管理
 slab
   – 图示
Linux系统内存管理
 slab
   – 其他
    •   Cache_cache
    •   外部slab
    •   内部slab
    •   Slab着色
Linux系统内存管理
 非连续内存
  – vmalloc
Linux系统内存管理
 进程内存管理
  – 管理的是什么?
   •   虚存or物理内存?
   •   谁来管理?内核态?用户态?
   •   进程内存有多大?
   •   管理的对象是什么?
Linux系统内存管理
 进程内存管理
  – 什么时候产生?变化?
   •   命令行,执行程序
   •   进程调用execve执行新程序
   •   Mmap on file
   •   栈不够用了
   •   IPC 如pipe
   •   扩展堆 malloc
   •   程序退出,销毁
   •   接口:brk,sbrk,mmap,munmap,shmat,shmdt,
       execve,exit,fork
Linux系统内存管理
 进程内存管理
  – 管理单元
  • Mm_struct /kernel thread mm_struct
  • Memory region vm_area_struct
Linux系统内存管理
 进程内存管理
  – Memory region 大小变化
Linux系统内存管理
 进程内存管理
  – Memory region 查询管理—红黑树
Linux系统内存管理
 进程内存管理
  – Memory region 查找
     • Find_vma 起始地址<=查找地址<=结束地址
     • Find_vma_intersection 找有交集的第一个memory region
     • arch_get_unmapped_area 查找从addr开始的长度为len的空区
       域
  – Memory region插入
     • insert_vm_struct 插入一个memory region
Linux系统内存管理
 进程内存管理
  – 分配一段线性地址空间 do_mmap
   •   检查参数合法性
   •   获取空闲区域Arch_get_unmapped_area
   •   计算新的flags
   •   find_vma_prepare
   •   检查内存是否超越限制
   •   分配vm_area_struct
   •   检查是否需要分配页表
   •   返回vm_area_struct的线性地址
 – 释放 do_unmap
Linux系统内存管理
 进程内存管理
  – Page fault 缺页中断
Linux系统内存管理
 进程内存管理
  – Demand paging
     • Handle_pte_fault
  – Copy on write
     • Fork会产生什么结果?
         –   为页表分配物理页
         –   为所有页分配新的物理页
         –   初始化新的页表
         –   然后将父进程的数据复制到子进程中
     • 只copy_page_tables
Linux系统内存管理
 进程内存管理
  – 创建进程空间
   • Clone copy_mm
 – 销毁进程空间
   • Mm_release
Linux系统内存管理
 进程内存管理
  – 堆管理
  •   Brk mmap系统调用
  •   Malloc calloc free sbrk
  •   Brk以页为单位分配内存
  •   小内存用brk,大内存用mmap
Linux系统内存管理
 Page cache
   – 定义
     • 内存对磁盘数据的cache
     • 减少对磁盘的访问
  – 场景
     •   存放目录,文件数据
     •   Mmap文件的数据
     •   直接从块设备读出来的数据
     •   Swap出去的数据
     •   IPC共享内存区
     •   主要是和文件相关
Linux系统内存管理
 Page cache
   – 数据结构
     • Address_space
     • Radix tree
     • Buffer page
Linux系统内存管理
 read
   – 参数
    •   Filp file object
    •   Buf 用户态buffer
    •   Count
    •   Ppos 偏移
  – 步骤               读请求



             用户空间              Page cache   磁盘


                    Copy_to_user
Linux系统内存管理
 write
  – 参数
    •   file file object
    •   Buf 用户态buffer
    •   Count
    •   Ppos 偏移
  – 步骤               写请求



             用户空间              Page cache   磁盘


                    Copy_from_user
Linux系统内存管理
 mmap
  – 为何需要mmap?
  – 数据结构
Linux系统内存管理
 页面替换算法PFRA
  – 设计哲学
   •   优先回收没有被引用的disk和memory cache,最好不修改页表
   •   所有用户空间的page都是可回收的
   •   回收共享page时解除所有引用
   •   只回收inactive page,LRU算法
Linux系统内存管理
 页面替换算法PFRA
  – 不可回收类型
   • Buddy中的空闲页
   • 保留页PG_reserved
   • Kernel栈,被LOCK的page
 – 可回收类型
   • Swappable
       – 匿名页
   • Syncable
       – Page cache & buffer page & Mapped page & disk cache
   • Discardable
       – Slab allocator cache & dentry cache
Linux系统内存管理
 页面替换算法PFRA
  – 回收时机
Linux系统内存管理
 页面替换算法PFRA
  – Active & Inactive list
  – 页面迁徙
Linux系统内存管理
 页面替换算法PFRA
  – Active & Inactive list
       • 匿名页开始在哪里?do_anonymous_page
       • 第一次读取,page cache在哪里?do_generic_mapping_read
   – 页面迁徙
       • 第二次读取page cache。 do_generic_mapping_read
       • Mmap的问题
Linux系统内存管理
 页面替换算法PFRA
  – Swap倾向
   • swap tendency = mapped ratio / 2 + distress + swappiness
   • Swappiness 60
   • mapped_ratio = ((global_page_state(NR_FILE_MAPPED)
     +global_page_state(NR_ANON_PAGES)) * 100) /vm_total_pages;
   • 32G内存,swappiness默认为60,distress为0,使用多少内存后
     会产生swap呢?
Linux系统内存管理
 页面替换算法PFRA
 Try_to_free_pages              Shrink_all_memory              balance_pgdat



                       Shrink_zones         Shrink_slab


                       Shrink_zone


  Shrink_active_list           Shrink_inactive_list


                                Shrink_page_list


         Add_to_swap             Try_to_upmap         __pagevec_release_nonlru
Linux系统内存管理
 页面替换算法PFRA
  – try_to_free_pages & balance_pgdat
  __pagevec_release_nonlru
                                 __free_one_page
       pagevec_free


     free_hot_cold_page


      free_pages_bulk        __page_find_buddy     __find_combined_index
第四章

高级内存管理
  --C库PTMALLOC
  --顺序分配
  --ARENA模式
  --TCMALLOC
  --管理哲学总结
高级内存管理
 C库ptmalloc
   – 为何要有高级内存管理?
   – Bins
高级内存管理
 C库ptmalloc
   – Fastbins
   – Unsortedbins
   – Top chunk
   – 优先级
              Fast bins     Exact bins
  小于72 B

            Unsorted bins   Exact bins   Sorted bins
  大于72 B

                            Top chunk     mmap
高级内存管理
 顺序分配
  – 有序分配,有序释放
  – 事先分配大内存,纯粹的指针操作
高级内存管理
 arena
   – Scope模式
   – 隐式释放,防侧漏
   • Void func(){
         –   Areana mem;
         –   Char *str = mem.get(size);
         –   Int *p = mem.get(size);
         –   看看看,就是这里,不紧绷~
   • }
高级内存管理
 tcmalloc
   – 与ptmalloc比较
     •   Thread Arena共享
     •   Zero lock
     •   系统调用少
     •   50ns per allocation
  – 实现
     • 非侵入式
高级内存管理
 tcmalloc
   – 原理
     • 线程独享
     • 集中管理
高级内存管理
 tcmalloc
   – 小内存分配
高级内存管理
 tcmalloc
   – 大内存分配
高级内存管理
 管理哲学总结
  – 重复使用
  – 集中管理
  – 大小粒度区分
  – 避免系统调用
  – 避免大锁
  – 尽量透明,不侵入
第五章

程序开发注意事项
  --架构对内存是否敏感
  --清楚程序所处的级别
  --如何防侧漏
程序开发注意事项
 架构对内存是否敏感
  – Where & when 何时何处分配内存?
    • 每个query来时?
    • 处理中间结果时?填充返回结果时?
  – How 如何分配内存?
    • 大内存还是小内存?如何满足需求?
    • 在栈上还是堆上?生命周期是短是长?
    • 频度是否很高?QPS?
  – What 你的内存和程序是什么样子滴?
    • 物理内存大小?
    • 32位机还是64位机?
    • 是否追求读写速度?
程序开发注意事项
 架构对内存是否敏感
  – 总结(敏感因素)
   •   有大内存分配
   •   内存依附于query,或者多线程
   •   频繁操作堆
   •   物理内存小,地址空间小
   •   要求速度快
 – 架构决定,人为优化
程序开发注意事项
 清楚程序所在的级别


              其他高级库


               C库


              系统调用


          处理器&物理内存
程序开发注意事项
 如何防侧漏
  – 程序级别
   • Arena
   • 少用堆
   • 第三方库
 – 工具级别
   • Valgrind
   • 其他
第六章

未来发展趋势
  --硬件
未来发展趋势
 硬件
  – 频率更高
  – 容量更大
  – 耗电量更小,电压更低
  – 工艺更精密
  – Flash盛行
谢谢
ZIJIA@TAOBAO.COM

Linux内存管理