andriod binder-ServiceManager守护进程
来源:互联网 发布:php将数组转换成字符串 编辑:程序博客网 时间:2024/04/28 15:09
ServiceManager是一个守护进程。它的main()函数源码如下:
frameworks/native/cmds/servicemanager/service_manager.c
int main(int argc, char **argv){ struct binder_state *bs; void *svcmgr = BINDER_SERVICE_MANAGER; bs = binder_open(128*1024); if (binder_become_context_manager(bs)) { ALOGE("cannot become context manager (%s)\n", strerror(errno)); return -1; } svcmgr_handle = svcmgr; binder_loop(bs, svcmgr_handler); return 0;}
/frameworks/native/cmds/servicemanager/binder.c
struct binder_state *binder_open(unsigned mapsize){ struct binder_state *bs; bs = malloc(sizeof(*bs)); ... bs->fd = open("/dev/binder", O_RDWR); ... bs->mapsize = mapsize; bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0); ... return bs;}
kernel/drivers/staging/android/binder.c
static int binder_open(struct inode *nodp, struct file *filp){ struct binder_proc *proc; binder_debug(BINDER_DEBUG_OPEN_CLOSE, "binder_open: %d:%d\n", current->group_leader->pid, current->pid); // 为proc分配内存 proc = kzalloc(sizeof(*proc), GFP_KERNEL); if (proc == NULL) return -ENOMEM; get_task_struct(current); // 将proc->tsk指向当前线程 proc->tsk = current; // 初始化proc的待处理事务列表 INIT_LIST_HEAD(&proc->todo); // 初始化proc的等待队列 init_waitqueue_head(&proc->wait); // 设置proc的进程优先级为当前线程的优先级 proc->default_priority = task_nice(current); binder_lock(__func__); binder_stats_created(BINDER_STAT_PROC); // 将该进程上下文信息proc保存到"全局哈希表binder_procs"中 hlist_add_head(&proc->proc_node, &binder_procs); // 设置进程id proc->pid = current->group_leader->pid; INIT_LIST_HEAD(&proc->delivered_death); // 将proc添加到私有数据中。 // 这样,mmap(),ioctl()等函数都可以通过私有数据获取到proc,即该进程的上下文信息 filp->private_data = proc; binder_unlock(__func__); if (binder_debugfs_dir_entry_proc) { char strbuf[11]; snprintf(strbuf, sizeof(strbuf), "%u", proc->pid); proc->debugfs_entry = debugfs_create_file(strbuf, S_IRUGO, binder_debugfs_dir_entry_proc, proc, &binder_proc_fops); } return 0;}
创建binder_proc对象,并把当前进程等信息保存到binder_proc对象,该对象管理IPC所需的各种信息并拥有其他结构体的根结构体;再把binder_proc对象保存到文件指针filp,以及把binder_proc加入到全局链表binder_procs。
kernel/drivers/staging/android/binder.c
//vm_area_struct则是描述进程虚拟地址信息的结构体。//vm_struct是描述内核虚拟地址信息的结构体。static int binder_mmap(struct file *filp, struct vm_area_struct *vma){ int ret; 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; if ((vma->vm_end - vma->vm_start) > SZ_4M) vma->vm_end = vma->vm_start + SZ_4M; //保证映射内存大小不超过4M mutex_lock(&binder_mmap_lock); //同步锁 //采用IOREMAP方式,分配一个连续的内核虚拟空间,与进程虚拟空间大小一致 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 = area->addr; //指向内核虚拟空间的地址 //地址偏移量 = 用户虚拟地址空间 - 内核虚拟地址空间 proc->user_buffer_offset = vma->vm_start - (uintptr_t)proc->buffer; mutex_unlock(&binder_mmap_lock); //释放锁 ... //分配物理页的指针数组,数组大小为vma的等效page个数; proc->pages = kzalloc(sizeof(proc->pages[0]) * ((vma->vm_end - vma->vm_start) / PAGE_SIZE), GFP_KERNEL); if (proc->pages == NULL) { ret = -ENOMEM; failure_string = "alloc page array"; goto err_alloc_pages_failed; } // 内核虚拟空间的内存大小 = 进程虚拟地址区域(用户空间)的内存大小 proc->buffer_size = vma->vm_end - vma->vm_start; vma->vm_ops = &binder_vm_ops; vma->vm_private_data = proc; //分配物理页面,同时映射到内核空间和进程空间,先分配1个物理页 if (binder_update_page_range(proc, 1, proc->buffer, proc->buffer + PAGE_SIZE, vma)) { ret = -ENOMEM; failure_string = "alloc small buf"; goto err_alloc_small_buf_failed; } buffer = proc->buffer; //binder_buffer对象 指向proc的buffer地址 INIT_LIST_HEAD(&proc->buffers); //创建进程的buffers链表头 list_add(&buffer->entry, &proc->buffers); //将binder_buffer地址 加入到所属进程的buffers队列 buffer->free = 1; //将空闲buffer放入proc->free_buffers中 binder_insert_free_buffer(proc, buffer); //异步可用空间大小为buffer总大小的一半。 proc->free_async_space = proc->buffer_size / 2; barrier(); proc->files = get_files_struct(current); proc->vma = vma; proc->vma_vm_mm = vma->vm_mm; return 0; ...// 错误flags跳转处,free释放内存之类的操作 return ret;}
static int binder_update_page_range(struct binder_proc *proc, int allocate, void *start, void *end, struct vm_area_struct *vma){ void *page_addr; unsigned long user_page_addr; struct page **page; struct mm_struct *mm; // 内存结构体 if (vma) mm = NULL; //binder_mmap过程vma不为空,其他情况都为空 else mm = get_task_mm(proc->tsk); //获取mm结构体 if (mm) { down_write(&mm->mmap_sem); //获取mm_struct的写信号量 vma = proc->vma; } //此处allocate为1,代表分配过程。如果为0则代表释放过程 if (allocate == 0) goto free_range; for (page_addr = start; page_addr < end; page_addr += PAGE_SIZE) { int ret; page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE]; //分配一个page的物理内存 *page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO); //物理空间映射到虚拟内核空间 ret = map_kernel_range_noflush((unsigned long)page_addr, PAGE_SIZE, PAGE_KERNEL, page); flush_cache_vmap((unsigned long)page_addr, (unsigned long)page_addr + PAGE_SIZE); user_page_addr = (uintptr_t)page_addr + proc->user_buffer_offset; //物理空间映射到虚拟进程空间 ret = vm_insert_page(vma, user_page_addr, page[0]); } if (mm) { up_write(&mm->mmap_sem); //释放内存的写信号量 mmput(mm); //减少mm->mm_users计数 } return 0;free_range: ... //释放内存的流程 return -ENOMEM;}
binder_update_page_range主要完成工作:分配物理空间,将物理空间映射到内核空间,将物理空间映射到进程空间
在Binder通信机制中,mmap()会将Server进程的虚拟地址和内核虚拟地址映射到同一个物理页面。那么当Client进程向Server进程发送请求时,只需要将Client的数据拷贝到内核空间即可!由于Server进程的地址和内核空间映射到同一个物理页面,因此,Client中的数据拷贝到内核空间时,也就相当于拷贝到了Server进程中。因此,Binder通信机制中,数据传输时,只需要1次内存拷贝!
http://qiangbo.space/2017-01-15/AndroidAnatomy_Binder_Driver/
http://wangkuiwu.github.io/2014/09/03/Binder-ServiceManager-Daemon/
http://gityuan.com/2015/11/01/binder-driver/
- andriod binder-ServiceManager守护进程
- binder守护进程servicemanager简介
- Android笔记 - Binder之守护进程servicemanager
- Android Binder机制(三) ServiceManager守护进程
- Android Binder机制(三) ServiceManager守护进程
- ServiceManager如何成为Binder进程通信的守护进程
- ServiceManager进程守护
- ServiceManager守护进程的注册
- android binder机制---servicemanager进程启动
- IPC(三)浅析Binder进程通信和ServiceManager
- Android Binder学习(二)之ServiceManager进程-我想成为管理员
- 【android】binder机制-servicemanager
- Android - Binder机制 - ServiceManager
- Android binder -serviceManager
- android binder 机制 (ServiceManager)
- Binder ServiceManager解析
- Binder通信守护者ServiceManager
- android binder 机制 (ServiceManager)
- Android HorizontalScrollView回弹效果
- 链表的创建和正向反向输出
- HTML——span、div、br、hr标签
- Linux进程通信(一)
- 547. 两数组的交
- andriod binder-ServiceManager守护进程
- three.j绘制性能监控
- C++ vector使用详解
- Qt SQlite实现级联删除
- AndroidStudio3.0.1安装视频
- 目标文件里有什么
- 【学习笔记】Python的 Hello world
- ubuntu安装nodejs
- HTML——格式标签