9.2 malloc和VM_LOCK 小结

  对于使用c语言的同学来说,malloc函数是很经典的函数,使用起来也很简单,可是内存实现并不简单。malloc函数其实是为用户空间分配进程地址空间,用内核术语来说就是分配一块VMA,相当于一个空的纸箱子。那什么时候才往纸箱子里装东西呢?有两种方式,一种是到了真正使用箱子的时候才往里面装东西,另一种是分配箱子的时候就装了你想要的东西。进程A里面的testA函数就是第一种情况,当使用这段内存时,CPU去查询页表,发现页表为空,CPU触发缺页中断,然后在缺页中断里一页一页地分配内存,需要一页给一页。进程B里面的testB函数,是第二种情况,直接分配已经装满的纸箱子,你要的虚拟内存都已经分配了物理内存并建立了页表映射。

    假设不考虑libc库的因素,malloc分配100Byte,那么内存会分配多少Byte呢?处理器MMU硬件丹玉处理最小单元是页,所以内核分配内存、建立虚拟地址和物理地址映射关系都是以页为单位,PAGE_ALIGN(addr)宏让地址addr按页面大小对齐。

    使用printf打印两个进程的malloc分配的虚拟地址一样的,那么内存中这两个虚拟地址空间会打架吗?其实每个用户进程有自己的一份页表,mm_struct数据结构中有一个pgd成员指向整个页表的基地址,在fork新进程的是偶会初始化一份页表。每个进程有一个mm_struct数据结构,包含一个属于进程自己的页表、一个管理VMA的红黑树和使用malloc分配内存返回的相同的虚拟地址,但其实它们是两个不同的VMA,分配被不同的两套页表来管理。 

    下图是malloc函数的实现流程,malloc的实现还涉及内存管理的几个重要函数。

1. get_user_pages()函数

    用于把用户空间的虚拟内存空间传到内核空间,内核空间为其分配物理内存并建立相应的映射关系,实现过程如下图:

long get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
        unsigned long start, unsigned long nr_pages, int write,
        int force, struct page **pages, struct vm_area_struct **vmas)

2. follow_page()函数

    通过虚拟地址addr寻找相应的物理页面,返回normal mapping页面对应的struct page数据结构,该函数会查询页表。

static inline struct page *follow_page(struct vm_area_struct *vma,
        unsigned long address, unsigned int foll_flags)

3. vm_normal_page()函数

    该函数由pte返回normal mapping的struct page数据结构,主要目的是过滤掉那些令人讨厌的special mapping的页面。

struct page *vm_normal_page(struct vm_area_struct *vma, unsigned long addr,
        pte_t pte);

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

byd yes

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值