地址空间细致入微+深入了解页表

目录

地址空间保存了什么?

页表到底是怎么存储的


我们都知道,我们进程看到的空间其实是虚拟内存,真正的内存是需要页表的映射才能找到真正的物理内存,那么我我们有两个问题的引出那么进程地址空间是保存了什么呢?页表是将全部地址都映射了对应到页表项吗?

地址空间保存了什么?

其实地址空间的每个区保存了两个地址。我们拿堆区做例子

地址空间细致入微+深入了解页表_第1张图片

mm_struct对堆区其实也只是保存了这个堆区使用的开始与结束,再mm_struct中其实有一个指针,指针指向着一个链双向边表的起始位置

地址空间细致入微+深入了解页表_第2张图片

vm_area_struct这个是个结构体


struct vm_area_struct {
    /* The first cache line has the info for VMA tree walking. */

    unsigned long vm_start;     /* Our start address within vm_mm. */
    unsigned long vm_end;       /* The first byte after our end address
                       within vm_mm. */
/*[vm_start, vm_end) 这么个情况,表示一块虚拟内存空间*/
    /* linked list of VM areas per task, sorted by address */
    struct vm_area_struct *vm_next, *vm_prev;
/*在mm->mmap链表中前后节点*/
    struct rb_node vm_rb;
/*插入到mm->mm_rb红黑树的节点*/
    /*
     * Largest free memory gap in bytes to the left of this VMA.
     * Either between this VMA and vma->vm_prev, or between one of the
     * VMAs below us in the VMA rbtree and its ->vm_prev. This helps
     * get_unmapped_area find a free area of the right size.
     */
    unsigned long rb_subtree_gap;
/*以当前vma为根,左子树中最大可用虚拟内存区域的大小*/
    /* Second cache line starts here. */

    struct mm_struct *vm_mm;    /* The address space we belong to. */
/*同一进程所有的vma指向的vm_mm是相同的*/
    pgprot_t vm_page_prot;      /* Access permissions of this VMA. */
/*访问权限*/
    unsigned long vm_flags;     /* Flags, see mm.h. */
/*属性,详看mm.h*/
    /*
     * For areas with an address space and backing store,
     * linkage into the address_space->i_mmap interval tree.
     *
     * For private anonymous mappings, a pointer to a null terminated string
     * in the user process containing the name given to the vma, or NULL
     * if unnamed.
     */
    union {
        struct {
            struct rb_node rb;
            unsigned long rb_subtree_last;
        } shared;
        const char __user *anon_name;
    };

    /*
     * A file's MAP_PRIVATE vma can be in both i_mmap tree and anon_vma
     * list, after a COW of one of the file pages.  A MAP_SHARED vma
     * can only be in the i_mmap tree.  An anonymous MAP_PRIVATE, stack
     * or brk vma (with NULL file) can only be in an anon_vma list.
     */
    struct list_head anon_vma_chain; /* Serialized by mmap_sem &
                      * page_table_lock */
    struct anon_vma *anon_vma;  /* Serialized by page_table_lock */

    /* Function pointers to deal with this struct. */
    const struct vm_operations_struct *vm_ops;
/*该vma操作函数,包括打开、关闭、建立映射三个函数*/

    /* Information about our backing store: */
    unsigned long vm_pgoff;     /* Offset (within vm_file) in PAGE_SIZE
                       units */
    struct file * vm_file;      /* File we map to (can be NULL). */
/*文件映射的文件信息,匿名映射为NULL*/
    void * vm_private_data;     /* was vm_pte (shared mem) */

    atomic_long_t swap_readahead_info;
#ifndef CONFIG_MMU
    struct vm_region *vm_region;    /* NOMMU mapping region */
#endif
#ifdef CONFIG_NUMA
    struct mempolicy *vm_policy;    /* NUMA policy for the VMA */
#endif
    struct vm_userfaultfd_ctx vm_userfaultfd_ctx;
#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
    seqcount_t vm_sequence;     /* Speculative page fault field */
    atomic_t vm_ref_count;      /* see vma_get(), vma_put() */
#endif
} __randomize_layout;

地址空间细致入微+深入了解页表_第3张图片

mm_struct中有个指针mmap指向由vm_area_struct构成的双向链表的头节点。

堆的数据范围其实就是vm_area_struct的多个结构体。

地址空间细致入微+深入了解页表_第4张图片

页表到底是怎么存储的

页帧与页框

页帧就是源文件编译完成后存储在磁盘的存储单位,也是以进程地址空间的方式进行编译的。

地址空间细致入微+深入了解页表_第5张图片

页框就是物理内存存储单位也是以4kb为单位的存储方式。

地址空间细致入微+深入了解页表_第6张图片

计算得知,我们的物理内存页框一共有:1024*1024*1024*4/1024=100w个页框,实际就是1024*1024。

地址空间细致入微+深入了解页表_第7张图片

 进程创建/打开文件步骤:

  1. 页表映射,查看对应数据是否在磁盘上。
  2. 发现对应数据存放在磁盘上,然后将数据加载到物理内存中
  3. 然后我们的将页表项的物理映射改为刚刚加载的物理内存地址

这其实就是缺页中断


但是有个问题,32位机器下,虚拟内存有2^32个地址,难道页表需要开辟2^32项吗?

假设一页项有10字节

2^32*10=40G。

但是我们的物理内存就4G,我去哪里搞剩下空间???所以页表其实也是一种复杂的结构,是一种多级页表映射关系。

地址空间细致入微+深入了解页表_第8张图片

随便写个虚拟地址0B0000 0000 0100 0000 0030 0000 0000 0012

地址空间细致入微+深入了解页表_第9张图片

 这就是实际的页表,这就是虚拟地址的查询逻辑。

假设,一二级页表每个页项20字节

20*1024*1024+1024*20=20MB。一个进程页表最多用这么多空间,相比之前40G好太多了。

一个知识点,二级页表并不是全部都有1024个,而是用按需申请使用。而一级页表是一定需要的。树根都没了,其他都是扯淡。

所以20MB只是最大,而不是一定是

你可能感兴趣的:(linux)