Linux系统内存管理简介

Linux系统内存管理简介

Linux内存管理之物理空间

Linux内核中有个全局变量mem_map,指向一个page数据结构的数组,每个page数据结构代表着一个物理页面,整个数据就代表着系统中的全部物理页面。页表项的高20位对于软件和MMU硬件有着不同的意义。对于软件,这是一个物理页面的序号,将这个序号用作下标就可以从mem_map找到这个物理页面的page数据结构。对于硬件,在低位补上12个0后就是物理页面的起始地址。

在内存映射的过程中,MMU首先检查的是P标志位,它指示所映射的页面是否在内存中。只有在P标志位为1的时候MMU才会完成映射的全过程;否则就会因为不能完成映射而产生一次缺页异常。

除了MMU硬件根据页面表项的内容进行页面映射外,软件也可以设置或检测页表的内容。对软件来说,页表项为0表示尚未为这个表项建立映射,如果表项不为0,但P标志位为0,则表示映射已经建立,但是所映射的物理页面不在内存中。

系统中的每一个物理页面都有一个page结构,系统在初始化时根据物理内存的大小建立起一个page结构数组mem_map,作为物理页面的仓库,里面的每个page数据结构都代表着系统中的一个物理页面。

page结构
typedef struct page{
    
    
    struct list_head list;              #双向链表
    struct address_space *mapping;
    unsigned long index;
    struct page *next_hash;
    atomic_t count;
    unsigned long flags;
    sturct list_head lru;
    unsigned long age;
    wait_queue_head_t wait;
    struct page **pprev_hash;
    struct buffer_head *buffers;
    void *virtual;
    struct zone_struct *zone;
}mem_map_t;

在page数据结构里面有一个zone_struct结构,该结构中有一组空闲区间队列(free_area_t)。为什么是“一组”队列,而不是“一个”队列呢?这是因为常常需要成”块“地分配在物理空间中连续的多个页面,所以要按块的大小分别加以管理。因此,在管理区数据结构中既要有一个队列来保持一些长度为1的物理页面,也要有一个队列来保持连续长度为2的页面块以及连续长度为4、8、16、…、直至1024。也就是说最大的连续页面块可达1024个页面,即4MB。

zone_sturct结构
#define MAX_ORDER 10
typedef struct free_area_struct{
    
    
    struct list_head    free_list;
    unsigned int        *map;
}free_area_t;

typedef struct zone_struct{
    
    
    /* Commonly accessed fields */
    spinlock_t  lock;
    unsigned long   offset;
    unsigned long   free_pages;
    unsigned long   inactive_clean_pages;
    unsigned long   inactive_dirty_pages;
    unsigned long   pages_min, pages_low, pages_high;
    /* free areas of different sizes */
    struct list_head    inactive_clean_list;
    free_area_t         free_area[MAX_ORDER];
    /* rarely used fields */
    char    *name;
    unsigned long   size;
    /* Disconting memory support fields */
    struct pglist_data *zone_pgdat;
    unsigned long   zone_start_paddr;
    unsigned long   zone_start_mapdr;
    struct page     *zone_mem_map;
    
}zone_t;

Linux内存管理之虚拟空间

在Linux系统中,每一个进程都有各自的虚存空间,也就是我们常说的用户空间。在进程中的task_struct结构中有一个mm_struct数据结构,该结构是进程整个用户空间的抽象。需要指出的是CPU实际进行的内存映射并不涉及mm_struct结构,而是通过页目录和页表进行的,但mm_struct描述了这种映射。

Linux虚存管理数据结构图:

在这里插入图片描述

mm_struct结构
struct mm_struct{
    
    
    struct vm_area_struct *mmap;        //虚存区间单链表,一个虚存空间可能包含多个虚存区间
    struct vm_area_struct *mmap_avl;    //虚存区间AVL树
    struct vm_area_struct *mmap_cache;  //指向最近一次使用的虚存空间
    pgd_t   pgd;//指向页目录,当内核调度一个进程运行时,将这个指针转换为物理地址,并写入控制寄存器CR3中。 
    /* mm_struct结构可能被多个进程共享*/
    atomic_t    mm_users;
    atomic_t    mm_count;               //使用此mm_struct的进程数量
    int map_count;                      //虚存区间数量
    /*由于mm_struct结构及其下属的vm_area_struct结构都有可能在不同的上下文受到访问,而这些访问又必须互斥,所以设置了信号量和锁*/
    struct  semaphore mmap_sem;
    spinlock_t  page_table_lock;
    
    struct list_head mmlist;
    
    unsigned long start_code, end_code, start_data, end_data;
    unsigned long start_brk, start_stack;
    unsigned long arg_start, arg_end, env_start, env_end;
    unsigned long rss, total_vm, locked_vm;
    unsigned long def_flags;
    unsigned long cpu_vm_mask;
    unsigned long swap_cnt;
    unsigned long swap_address;
    
    mm_context_t context;
};
vm_area_struct结构

vm_area_struct结构是对虚存空间的一个抽象。

struct vm_area_struct{
    
    
    struct mm_struct *vm_mm;
    unsigned long vm_start;         //指定虚存区间起始位置
    unsigned long vm_end;               //指定虚存区间结束位置(不包含)
    
    struct vm_area_struct *vm_next;     //同一个进程的虚存空间按照虚存地址的高低次序排序,用链表链起来
    
    pgprot_t vm_page_prot;
    unsigned long vm_flags;
    /* 内核中给定一个虚拟地址而要找出其所属区间是一个频繁使用到的操作,如果每次都要顺着vm_next在
    链表中作线性搜索,效率很低。所以需要建立一个AVL树保存虚存区间的指针。*/
    short vm_avl_height;
    struct vm_area_struct *vm_avl_left;
    struct vm_area_struct *vm_avl_right;
    
    struct vm_area_struct *vm_next_share;
    struct vm_area_struct **vm_pprev_share;
    
    struct vm_operations_struct *vm_ops;
    unsigned long vm_pgoff;
    struct file *vm_file;
    unsigned long vm_raend;
    void *vm_private_data;
}

猜你喜欢

转载自blog.csdn.net/qq_38600065/article/details/107452478