Linux Kernel 及 binder mmap实现


1. 简介

    对于mmap在用户态通过函数以下函数进行调用:

  1. void*   mmap( void*  addr,  size_t  size, int  prot, int  flags, int  fd,  long  offset )  

    然后进入系统调用。 

2. Kernel mmap实现

1)然后进入系统调用,其系统调用号为: 

kernel/arch/arm/include/asm/unistd.h

#define __NR_mmap2   (__NR_SYSCALL_BASE+192)

2)触发软中断

     其ISR 代码位于kernel/arch/arm/kernel/entry-common.S的ENTRY(vector_swi), __NR_mmap2对应的函数为:sys_mmap2(位于linux/arch/arm/kernel/calls.S)

3)sys_mmap2的实现

位于kernel/arch/arm/kernel/entry-common.S,实现代码如下:

  1. /* 
  2.  * Note: off_4k (r5) is always units of 4K.  If we can't do the requested 
  3.  * offset, we return EINVAL. 
  4.  */  
  5. sys_mmap2:  
  6. #if PAGE_SHIFT > 12   
  7.         tst r5, #PGOFF_MASK  
  8.         moveq   r5, r5, lsr #PAGE_SHIFT - 12  
  9.         streq   r5, [sp, #4]  
  10.         beq sys_mmap_pgoff  
  11.         mov r0, #-EINVAL  
  12.         mov pc, lr  
  13. #else   
  14.         str r5, [sp, #4]  
  15.         b   sys_mmap_pgoff  
  16. #endif  

4) 调用sys_mmap_pgoff

在kernel/include/linux/syscalls.h中定义如下:

  1. asmlinkage long sys_mmap_pgoff(unsigned long addr, unsigned long len,  
  2.             unsigned long prot, unsigned long flags,  
  3.             unsigned long fd, unsigned long pgoff);  

6)sys_mmap_pgoff实现
在kernel/mm/mmap.c中实现如下:

  1. SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,  
  2.         unsigned long, prot, unsigned long, flags,  
  3.         unsigned long, fd, unsigned long, pgoff)  
  4. {  
  5.     struct file *file = NULL;  
  6.     unsigned long retval = -EBADF;  
  7.   
  8.     if (!(flags & MAP_ANONYMOUS)) {  
  9.         audit_mmap_fd(fd, flags);  
  10.         if (unlikely(flags & MAP_HUGETLB))  
  11.             return -EINVAL;  
  12.         file = fget(fd);  
  13.         if (!file)  
  14.             goto out;  
  15.     } else if (flags & MAP_HUGETLB) {  
  16.         struct user_struct *user = NULL;  
  17.         /* 
  18.          * VM_NORESERVE is used because the reservations will be 
  19.          * taken when vm_ops->mmap() is called 
  20.          * A dummy user value is used because we are not locking 
  21.          * memory so no accounting is necessary 
  22.          */  
  23.         len = ALIGN(len, huge_page_size(&default_hstate));  
  24.         file = hugetlb_file_setup(HUGETLB_ANON_FILE, len, VM_NORESERVE,  
  25.                         &user, HUGETLB_ANONHUGE_INODE);  
  26.         if (IS_ERR(file))  
  27.             return PTR_ERR(file);  
  28.     }  
  29.   
  30.     flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);  
  31.   
  32.     down_write(¤t->mm->mmap_sem);  
  33.     retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);  
  34.     up_write(¤t->mm->mmap_sem);  
  35.   
  36.     if (file)  
  37.         fput(file);  
  38. out:  
  39.     return retval;  
  40. }  

     其功能为:从当前进程中获取用户态可用的虚拟地址空间(vm_area_struct *vma),在mmap_region中真正获取vma,然后调用file->f_op->mmap(file, vma),调用具体的支持mmap的驱动来处理。

     下面以binder驱动为例。

  • 1
  • 2
  • 3
  • 下一页

相关内容