Linux Kernel 及 binder mmap实现
Linux Kernel 及 binder mmap实现
1. 简介
对于mmap在用户态通过函数以下函数进行调用:
- 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,实现代码如下:
- /*
- * Note: off_4k (r5) is always units of 4K. If we can't do the requested
- * offset, we return EINVAL.
- */
- sys_mmap2:
- #if PAGE_SHIFT > 12
- tst r5, #PGOFF_MASK
- moveq r5, r5, lsr #PAGE_SHIFT - 12
- streq r5, [sp, #4]
- beq sys_mmap_pgoff
- mov r0, #-EINVAL
- mov pc, lr
- #else
- str r5, [sp, #4]
- b sys_mmap_pgoff
- #endif
4) 调用sys_mmap_pgoff
在kernel/include/linux/syscalls.h中定义如下:
- asmlinkage long sys_mmap_pgoff(unsigned long addr, unsigned long len,
- unsigned long prot, unsigned long flags,
- unsigned long fd, unsigned long pgoff);
6)sys_mmap_pgoff实现
在kernel/mm/mmap.c中实现如下:
- SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
- unsigned long, prot, unsigned long, flags,
- unsigned long, fd, unsigned long, pgoff)
- {
- struct file *file = NULL;
- unsigned long retval = -EBADF;
- if (!(flags & MAP_ANONYMOUS)) {
- audit_mmap_fd(fd, flags);
- if (unlikely(flags & MAP_HUGETLB))
- return -EINVAL;
- file = fget(fd);
- if (!file)
- goto out;
- } else if (flags & MAP_HUGETLB) {
- struct user_struct *user = NULL;
- /*
- * VM_NORESERVE is used because the reservations will be
- * taken when vm_ops->mmap() is called
- * A dummy user value is used because we are not locking
- * memory so no accounting is necessary
- */
- len = ALIGN(len, huge_page_size(&default_hstate));
- file = hugetlb_file_setup(HUGETLB_ANON_FILE, len, VM_NORESERVE,
- &user, HUGETLB_ANONHUGE_INODE);
- if (IS_ERR(file))
- return PTR_ERR(file);
- }
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
- down_write(¤t->mm->mmap_sem);
- retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
- up_write(¤t->mm->mmap_sem);
- if (file)
- fput(file);
- out:
- return retval;
- }
其功能为:从当前进程中获取用户态可用的虚拟地址空间(vm_area_struct *vma),在mmap_region中真正获取vma,然后调用file->f_op->mmap(file, vma),调用具体的支持mmap的驱动来处理。
下面以binder驱动为例。
|
评论暂时关闭