Binder驱动之内存映射全解

本文详细探讨了Android Binder驱动中的内存映射过程,包括如何通过系统调用进行内存映射、物理内存的分配与释放。重点介绍了Binder如何在内核态和用户态之间建立地址映射,使得数据只需拷贝一次,从而提高通信效率。同时总结了Binder通信内存映射的限制和管理策略。

Binder通过open调用打开后,需要用户态进程需调用mmap进行内存映射。mmap系统调用,经过VFS最终会调用到binder驱动注册的binder_mmap函数。这里我们将揭开Binder通信高效的本质原因,:)

一 内存映射函数的实现 binder_mmap(kernel/drivers/android/binder.c)

static int binder_mmap(struct file *filp, struct vm_area_struct *vma/*用户态虚拟地址空间描述,地址空间在0~3G*/)
{
   
   
    int ret;
    /* 一块连续的由vmalloc分配内核虚拟地址空间描述,从 VMALLOC_START到VMALLOC_END*/
    struct vm_struct *area;
    struct binder_proc *proc = filp->private_data;
    const char *failure_string;
    struct binder_buffer *buffer;

    if (proc->tsk != current)
        return -EINVAL;

    //申请空间不能大于4M,如果大于4M就改为4M大小。app默认是1M左右
    if ((vma->vm_end - vma->vm_start) > SZ_4M)
          vma->vm_end = vma->vm_start + SZ_4M;

    //检查vma是否被forbidden,vma是一块连续的用户态虚拟内存地址空间的描述
    if (vma->vm_flags & FORBIDDEN_MMAP_FLAGS) {
   
   
          ret = -EPERM;
          failure_string = "bad vm_flags";
        goto err_bad_arg;
    }

    //打开VM_DONTCOPY,关闭VM_MAYWRITE
     vma->vm_flags = (vma->vm_flags | VM_DONTCOPY) & ~VM_MAYWRITE;

    //加上binder_mmap_lock互斥锁,因为接下来要操作proc结构体,可能发生多线程竞争
     mutex_lock(&binder_mmap_lock);

    //一个进程已经有一次mmap,如要执行新的map,需先将之前的unmap。
    if (proc->buffer) {
   
   
          ret = -EBUSY;
          failure_string = "already mapped";
          goto err_already_mapped;
    }

    /* 获取一块与用户态空间大小一致的内核的连续虚拟地址空间,
     * 注意虚拟地址空间是在此一次性分配的,物理页面却是需要时才去申请和映射
    */
    area = get_vm_area(vma->vm_end - vma->vm_start, VM_IOREMAP);
    if (area == NULL) {
   
   
          ret = -ENOMEM;
          failure_string = "get_vm_area";
        goto err_get_vm_area_failed;
    }

    //将内核虚拟地址记录在proc的buffer中 
     proc->buffer = area->addr;

    /* 记录用户态虚拟地址空间与内核态虚拟地址空间的偏移量,
     * 这样通过buffer和user_buffer_offset就可以计算出用户态的虚拟地址。
    */
     proc->user_buffer_offset = vma->vm_start - (uintptr_t)proc->buffer;

    /*释放互斥锁*/
     mutex_unlock(&binder_mmap_lock);
#ifdef CONFIG_CPU_CACHE_VIPT
    /* CPU的缓存方式是否为: VIPT(Virtual Index Physical Tag):使用虚拟地址的索引域和物理地址的标记域。
     * 这里先不管,有兴趣的可参考:https://blog.csdn.net/Q_AN1314/article/details/78980191
    */
    if (c
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值