您的位置:

Linux内存管理

一、内存基础

1、内存的种类 - SRAM,DRAM,SDRAM,DDR SDRAM

Static RAM(静态随机存取内存)是保持数据存储的最简单的形式。Dynamic RAM(动态随机存取内存)是一种需要定时重置的内存,之所以需要这样做是因为电荷会从RAM细胞中“泄漏”出去。写操作可恢复电荷,刷新操作则需要一个定时器和一些电容来存储电荷。 SDRAM (synchronous dynamic RAM)是DRAM的进化版本,具有更高的带宽和更低的延迟。DDR SDRAM (double data rate SDRAM) 使用更复杂的信号路线,在一个时钟周期内传输更多的数据。

2、内存物理分区 - 根据内存大小自动分为几个物理分区

3、内存虚拟分区 - 操作系统通过将主存分成小块来提供更高的内存管理

二、内存管理

1、进程和虚拟地址

/**
 * 用于访问主物理内存的页表在页表所在的页中进行到原始形式和物理形式之间转换的逻辑地址计算工具
 */
#define virt_to_phys(virt)                 (__pa(virt))

/**
 * 通过计算出查找真正的物理地址的单元的索引,从而找到虚拟地址对应的物理地址
 * @param[in] dir 目录指针
 * @param[in] address 虚拟地址
 * @return 对应的物理地址指针
 */
#define PTE_ADDR(hi, lo)                    ((pte_t *)((w32)PTE_BASE + (((hi) << PAGE_DIR_SHIFT) | ((lo) << PAGE_TABLE_SHIFT))))

#define PKMAP_BASE                          PAGE_OFFSET
#define PKMAP_ADDR(vaddr)                   (PKMAP_BASE + (((unsigned long)(vaddr) - PAGE_OFFSET) >> 2))
#define pte_offset_virt_to_phys(pdir, address) \
    (*(pte_t **)(&pdir[PTE_INDEX(address)]) + ((address & (PAGE_SIZE - 1)) >> 2))

2、物理内存和虚拟内存

3、内存中断和锁定 - 内核不适用于虚拟内存分页,但可以锁定数据以保持coherency

三、内存分配和释放

1、一般内存池、缓冲区链表和内存碎片

2、内核内存配置和释放 - 调用kmalloc和kfree

/**
 * 分配内核中的内存
 * flags:GFP_KERNEL/fatal_signals_pending
 */
#define kmalloc_(size, flags, align)                                             \
({  void *__kmalloc_result;                                                       \
    BugOn(in_interrupt());                                                        \
    __kmalloc_result = mem_kmalloc(size, flags, align);                            \
    if (unlikely(!__kmalloc_result)) {                                             \
        show_low_mem();                                                             \
        panic("KMALLOC FAILED size %d\n", (int)(size));                              \
    }                                                                               \
    __kmalloc_result;                                                               \
})

/**
 * 释放内核内存
 */
#define kfree_(addr) mem_kfree(addr)

3、内存碎片整理技术 - 使用压缩和紧缩分区管理策略来减少内存碎片

四、内存映射

1、内存管理单元

/**
 * @file memory.h
 * @brief 内存管理单元
 */

#include "pt.h"

struct mm_struct_tag;

/**
 * 页表
 */
typedef struct page_map_contents_tag {
        /**
         * 在上下文中启用页表,该上下文由paging_init()调用生成。所有我们真正关心的页帧都是在初始化上下文时创建的
         */
        pt_t *pt_root;
        int user_pdir_idx;
        /**
         * 首先,我们为一个进程保留单独的页表
         * mm是一个进程上下文的表示
         */
        struct mm_struct_tag *owner;
} pmc_t;

/**
 * 物理页
 */
typedef struct pmem_contents_tag {
        /**
         * 指向内存中该物理页在内存中的位置的指针
         */
        u32 *virt;
        /**
         * 引用计数,表示有多少用户或内核空间块正在使用该页
         */
        u32 usage_count;
} ppc_t;

/**
 * 内存管理单元
 */
typedef struct memory_map_contents_tag {
        /**
         * 整个机器的总物理内存(KBs),在启动时静态分配
         */
        u32 phys_mem_bytes;
        /**
         * 物理页数
         */
        u32 num_phys_pages;
        /**
         * 所有物理页的数组,每个pg和PgMap存储指向其他pmem_contents_struct和page_map_contents_struct结构的指针,用于向新的内存映射添加额外的页
         */
        ppc_t *ppc;
        pmc_t *pmc;
        /**
         * 当前的物理页数,以enable_paging()被调用时初始化为num_phys_pages,然后在每次分配新物理页时减少
         */
        u32 available_phys_pages;
} mmc_t;

2、分页和段式内存管理

3、用户态和内核态的内存访问权限 - 运行用户程序时,访问虚拟地址

五、内存监测和优化

1、监视内存使用情况 - 使用各种工具和技术来掌握内存使用情况,如top,free和vmstat等

2、内存优化 - 避免内存泄漏、碎片以及使用内存和缓存的过度

3、第三方工具 - 针对内存监测和优化的各种第三方工具