Binder mmap
By yacoo
这篇小文,只说明一件事情,如何从应用层的binder mmap调用到binder驱动mmap。
1. 先给出两个打开binder设备的场景,我们可以看到,mmap 空间的size并不一样。
l service_manager.c
intmain(int argc, char **argv)
bs = binder_open(128*1024);
structbinder_state *binder_open(unsigned mapsize)
bs->fd = open("/dev/binder", O_RDWR);
bs->mapsize = mapsize;
bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE,bs->fd, 0);
b6ea8000-b6ec8000r--p 00000000 00:0c 8237 /dev/binder--- size = 128K
l ProcessState.cpp
ProcessState::ProcessState()
: mDriverFD(open_driver())
staticint open_driver()
int fd = open("/dev/binder",O_RDWR);
if(mDriverFD >= 0) {
mVMStart = mmap(0,BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
74c55000-74d53000r--p 00000000 00:0c 8237 /dev/binder --- size = BINDER_VM_SIZE
#defineBINDER_VM_SIZE ((1*1024*1024) - (4096 *2))
2. 下来,分析下应用层的binder mmap是怎么走到binder驱动里面的。
对于mmap在用户态通过函数以下函数进行调用:
void* mmap( void* addr, size_t size, int prot, int flags, int fd, long offset )
然后进入系统调用,其系统调用号为:
kernel/arch/arm/include/asm/unistd.h
#define__NR_mmap2 (__NR_SYSCALL_BASE+192)
unistd32.h:
__SYSCALL(192,sys_mmap_pgoff)
kernel/arch/arm/kernel/entry-common.S:
/*
* Note: off_4k (r5) is always units of4K. 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
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);
kernel/mm/mmap.c:
SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
unsigned long, prot, unsignedlong, flags,
unsigned long, fd, unsignedlong, pgoff)
{
retval = do_mmap_pgoff(file, addr, len,prot, flags, pgoff);
unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
unsigned long len,unsigned long prot,
unsigned long flags,unsigned long pgoff,
unsigned long*populate)
{
/* Obtain the address to map to. weverify (or select) it and ensure
* that it represents a valid section of theaddress space.
*/
addr= get_unmapped_area(file, addr, len, pgoff, flags); --- 注意,此处,kernel已经提供了虚拟地址供该map空间使用。
addr = mmap_region(file, addr, len,vm_flags, pgoff);
unsigned longmmap_region(struct file *file, unsigned long addr,
unsigned long len, vm_flags_tvm_flags, unsigned long pgoff)
{
/*
* Can we just expand an old mapping?
*/
vma = vma_merge(mm, prev, addr, addr +len, vm_flags, NULL, file, pgoff, NULL);
/*
* Determine the object being mapped and callthe appropriate
* specific mapper. the address has alreadybeen validated, but
* not unmapped, but the maps are removed fromthe list.
*/
vma = kmem_cache_zalloc(vm_area_cachep,GFP_KERNEL);
vma->vm_file =get_file(file);
error= file->f_op->mmap(file, vma); --- 至此,终于调用到了binder驱动自身的mmap。
binder.c
static int binder_mmap(struct file *filp, struct vm_area_struct*vma)
{
参考链接:http://blog.csdn.net/myarrow/article/details/7207628