Binder概述,快速了解Binder体系

前语

众所周知,Binder是Android系统中最主要的进程间通讯套件,更详细一点,许多文章称之为Binder驱动,那为什么说它是一个驱动呢,驱动又是何物,让我们自底接口crc错误计数向上,从内核中的Bindelinux系统装置r来一步步揭开它的面纱。本文重点架构是什么意思在帮助读者关于B接口是什么inder系统有一个简略的了解,所以写得比较抽象,后续文章会详细剖析。工商银行客服电话

Binder到linux系统装置底是什么

Android系统内核是Linux,每个进程有自己的虚拟地址空间,在32位系统下最大是接口crc错误计数4GB,其间3GB为用户空间,1GB为内核空间;每个进程用户空间相对独立,而内核空狗狗币间是相同的架构师和程序员的差异,可以同享,如下图

Binder概述,快速了解Binder系统

Linux驱动作业在内核空间,狭义上讲是系统用于操linux创立文件控硬件的中心程序,可是归根到底它只是一个程序一段代码,所以详细完结并不一linux是什么操作系统定要和硬件有关。Bi工商银行客服电话nder便是将自己注册为一个misc类型的驱动,不触及硬件操作,一起自身作业于内核中,所接口测验以可以当作不同进程间的桥梁完结I链表逆序PC功用。

Linux最大的特征便是悉数皆文件,驱架构师需求把握哪些常识动也链表和数组的差异不破例,悉数linux常用指令驱动都会被挂载在文件系统dev目录下,Binder对应的目录是/dev/binder,注册驱动时将open release mmap等系统调用龚俊注册到Binder自己的函数,这样的话在架构图用户空间就可以经过系统调用以拜访文件的办法运用Binder。下面来大约看一下相关代码。

devic接口类型e_linux指令initcall函数用于注册驱动,由系统调用

binder_init中调用misc_register注册一个名为binder的misc驱动,一起指定函数映射,链表c言语将binder_open映射到系统调用open,这样就能宫颈癌前期症状够经过open("/dev/bindlinuxer")来调用binder_open函数了

drivers/andr架构图oid/binder.c

//接口测验面试题 驱动函数映射
static const struct file_operations binder_fops = {
.owner = THIS_MODULE,
.poll = binder_poll,
.unlocked_ioctl = binder_ioctl,
.compat_ioctl = binderlinux常用指令_ioctl,
.m接口map = binder_mmap,
.open = binder_open,
.flush =工商银行客服电话 b链表排序inder_flush,
.release = binder_release,
};
// 注册驱动参数结构体
sta架构师需求把握哪些常识tic struct miscdevice bin链表结构der_miscdev = {
.minor = MI接口测验SC_DYNAMIC_MINOR,
// 驱动称谓
.name = "b架构师需求把握哪些常识indlinux操作系统基础常识er接口测验",
.fops = &binder_fops
};
static int binder_open(struct inode *nodp, strlinux常用指令uct file *filp){......}
static int binder_mmap(struct file *filp, struct vm_area_stru架构图怎么做wordct *vma){......linux系统}
s架构师和程序员的差异talinux必学的60个指令tic int __init binder_in工程造价it(void)
{
int ret;
// 创立名为binder的单线程的作业部队
binder_deferred_workqueue = create_singlethread_workqueue("binder");
if (linux创立文件!binder_deferred_workqueue)
return -ENOMEM;
......
// 注册驱动,misc设备其实也便是特别的字符设备
ret = misc_register(&a工商管理mp;binder_miscdev);
....架构师和程序员的差异..
return ret;
}
// 驱动注册函数
device_initcall(binder_init);

Binder的简略通讯进程

一个进程怎样经过bin架构师需求把握哪些常识der和linux必学的60个指令另一个进程通讯?最简单的流程如下

  1. 接纳端进程开启一个专门的线程Go,经过系统调用在binder驱动(内核)中先注册工商银行此进程(创立保存一个bidner_proc),驱动为接纳端进程创立一个使命部队(biner_proc.todo)
  2. 接纳端线程开始无限循环,经过系统调用不断拜访binlinux必学的60个指令der驱动,假定该进程对应的使命队宫颈癌伍有使命则回来处理,不然阻塞该架构师和程序员的差异线程直到链表排序有新使命入队
  3. 发送端也经过系统调用拜访,架构师找到方针进程,将使命丢到方针进程的部队中,然后唤醒方针进程中休眠的线程处理该使命,即完结通讯

在Binder驱动中以binder_proc结构体代表一个进程,binder_thread代表一个线链表不具有的特点是程,binLinuxder_proc.todo即为进程需求处理的来自其他进程的使命部队

struct binder_proc {
// 存储悉数binder_proc的链表
struct hlist_node架构师 proc_node;
// binder_thread红黑树
struct rb_root threads;
// binder_proc进程内的binder实体组成的红黑树
struct rb_root nodes;
......
}

Binder的一次拷贝

众所周知Binder的优势在于一次拷贝效率高,很多博客工商管理现已说烂了,那么什么是一次拷贝,怎样完结,产google生在哪里,这儿尽量接口的效果简单地解释一下。

上面现已说过,不同进程经过在内核中的Binder驱动来进行通讯,可是用户空间和内核空间是隔脱离的,无法彼此拜访,他们之间传递数据需求凭借copy_from_user和copy_to_use狗狗币r两个系统调用,把用户/内核空间内存中的数据拷贝到内核/用户空间的内存中接口文档,这样的话,假定两个进程需求进行一次单向通讯则需求进行两次拷贝,如下图。

Binder概述,快速了解Binder系统

Binder单次通讯只需求进行一次拷贝,由于它运用了内存映射,将一块物理内存(若干个物理页)别离映射到接纳端用户空间和内核空间,抵达用户空间和内核空间同享数据的意图。

发送端要向接纳接口是什么端发送数据时,内核直接经过copy_from_user将数据拷贝到内核空间映射区,此时由于同享物理内存,接纳进程的内存映射区也就能拿到该数据了,如下图。

Binder概述,快速了解Binder系统

代码完结部分

用户空间经过mmap系统调用linux必学的60个指令,调用到Binder驱动中binder_mmap函数进架构图模板行内存映射,这部分代码比较难读,感兴趣的能linux创立文件够看一下。

dr链表排序ivers/android/binder.c

binder_mmap创立binder_buffer,记载进程内存映射相关信息(用户空间映射地址,内核空间映射地址等)

static int binder_mmap(struct filinux常用指令le *filp, struct vm接口的效果_area_s接口类型truct *vma)
{
int ret;
//内核虚拟空间linux是什么操作系统
st链表c言语ruct vm_struct *area;
struct binder_proc *proc = filp->pr接口测验面试题ivate_data;
const char *failure_string;
// 每一次Binder传输数据时,都会先从Binder内存缓存区中分配一个binder_buffer来存储传输数据
struct binder_buffer *buffer;
if (proc->tsk != current)
return -EINVlinux系统AL;
// 保证内存映接口的效果射巨细不逾越4M
if ((vma->vm_end - vma->vm_start) > SZ_4linux常用指令M)
vma->v架构图怎么做wordm_en链表回转d = vma->vm_start + SZ_4M;
......
// 选用IOREMAP办法架构师,分配一个连续的内核虚拟空间,与用户进程虚拟空间巨细一起
// vma是从用户空间传过来的虚拟空间结构体
area = get_vm_area(vma->vm_架构图end - vma->vm_start, VM_IOREM架构师薪酬一月多少AP链表c言语);
if (area == NULL) {
ret = -ENOMEM;
failure_string = "get_vm_ar接口测验面试题ea";
goto err_ge链表排序t_vm_area_failed;
}
// 指向内核虚拟空间的地址
plinux常用指令roc->buffer = area工商银行客服电话->架构师adlinux系统装置dr;
// 用户虚拟空间开始地址 - 内核虚拟空间开始地址
proc->user_buffer_offset = vma->vm_start - (uintpt链表与数组的存储结构有什么不同r_t)proc->buffer;
......
// 分配物理页的指针数组,数组巨细为vma的等效page个数
proc->pa宫颈癌ges = kzalloc(siz接口测验面试题eof(proc->pages[0]) * ((vma->接口卡vm_end - vma->vm_start) / PAGE_SIZE), GFP_KERNEL接口的界说);
if (proc->pages == NULL工商银行) {
ret = -ENOMEMgoogle;
failure_string = "alloc page arr架构师ay";
goto err_alloc_pages_failed;
}
proc->buf工商银行客服电话fer_size = vma->vm_end - vGoma->vm_start;
vma->vm_ops = &binder_vm_ops;
vma->vm_private_data = proc;
// 分配物理linux系统装置页面,一起映射到内核空间和进程空间,先分配1个物理页
if (binde接口测验r_update_page_range(proc, 1, proc->buffer, proc->buffer + PAGE_SIZE, vma)) {
ret = -ENOMEM;
failure_string = "alloc small buf";
go链表to err_alloc_small_buf_failed;
}
buffer = proc->buffer;
// buffer刺进链表
IN链表回转IT_LIST_HEAD(&proc->buffers);
list_add(&buffer->linux是什么操作系统entry, &proc->buffers);
buffer->free = 1;
binder_insert_free_buffer(proc, bufferlinux常用指令);
// oneway异步可用巨细为总空间的接口测验面试题一半
proc->free_async_架构是什么意思space = proc->buffer_size / 2;
barrier();
proc->fil接口crc错误计数es = get_files_struct(current);
proc-&链表的创立gt;vma = vma;
proc->vma_vm_mm = vma->vm_mm;
/*pr_info("binder_mmap: %d %llinux系统装置x-%lx maps %pn",
proc->p工程造价id, vma-&linux常用指令gt;vm_start, vma->vm_end, plinux是什么操作系统roc->buffer);*/
return 0;
}

binder_update_page_range 函数为映射地址分配物理页,这儿先分配一个物理页(4KB),google然后将这个物理页一起映射到用户空间地址和内存空间地址

static int binder_update_page_range(structgoogle binder_proc *proc, int allocate,
void *start, void *end,
struct vm_链表与数组的存储结构有什么不同area_链表c言语struct *vma)
{
// 内核映射区开始地址
void *page_addr;
// 用户映射区开始地址
unsigned long user_page_addr;
struct page **page;
// 内架构师需求把握哪些常识存结构体
struct mm_struct *mm;
if (end <= start)
return 0;
......
/接口测验面试题/ 循环分配悉数物理页,并别离建立架构工程师用户空间和内核空间对该物理页链表与数组的存储结构有什么不同的映射
for (page_addr = start; page_addr < end; page_addr +架构师薪酬一月多少=链表回转 PAGE_SIZE) {
int ret;
page = &链表排序proc->pages[(page_addr - proc->buffer) / PAGE_SIZE];
BUG_Olinux必学的60个指令N(*page);
// 分配一页物理内存
*page = al接口的效果loc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO);
if (*page == NULL) {
pr_err("%d: bindlinux重启指令er_alloc_buf工商银行客服电话 failed for page at %pn",
pro接口的效果c->pid, page_addr);
goto err_alloc_page_failed;
}
// 物理内存映射到内核虚拟空间
ret = map_kernel_range链表排序_noflush((unsigned long)page_addr,
PAGE_SIZE, PAGE_KERNEL, page);linux指令
flush_cache_vmap((unsigned long)page_addr,
// 用户空间地链表址 = 内核地址+偏移
user_page_a公积金ddr =
(uintptr_t架构图怎么做word)page_addr + proc->user_buffer_offset;
// 物理空间映射到用户虚拟空间
ret = vm_inslinux操作系统基础常识ert_pag接口是什么e(vma, user_page_a公积金ddr, page[接口是什么0]);
}
}

binder_mm接口测验面试题ap函数中调用binder_update_page_range只为映射差异配了一个物理页的空间,在B链表c言语indeLinuxr开始通讯时,会再经过binder_alloc_bulinux常用指令f函数分配更多物理页,这是后话了。

Binder套件架构

内核层的Binder驱动现已供给了IPC功用架构工程师,不过还需求在framework nat架构图怎么做wordive层供给一些关于驱动层的调用封装,使framework开发者更易于运用,linux操作系统基础常识由此封装出了native Binder;一起,由于framework native层是c/c++言语完结,关于应用开发者,需求愈加便当的Java层的封装,衍生出Java Binder;毕竟在此之上,为了削减重复代linux码的编写和标准接口,在J链表与数组的存储结构有什么不同ava Binde狗狗币r的基础上又封装出了AIDL。经过层层封装,在运用者运用AI接口DL时关于Binder基本上是无感知的。

这儿贴一张架构图。

Binder概述,快速了解Binder系统
Native层:BpBinder代表服务端Binder架构图的一个linux常用指令署理,内部有一个成员mHandle便是服务端Binder在驱动层的句柄,客架构是什么意思户端经过调用BpBinder::transact传入该句柄,经过驱动层和服务端BBinder发生会话,毕竟服务端会调用到BBinder::onTransact。在这儿两者之间架构图怎么做word经过约定好的code来标识会话内容。

Java层:Java层是对native层的封装,本Go质没有什么差异,。linux

AIDL:AIDL生成的代码关于Binder进行了进一步封装,<接口>.St接口类型ub对应服务端Binder,<接口&g接口和抽象类的差异tlinux;.Stu公积金b.Proxy标识客户端,内部持有一个mRemote实例(BinderProxy),aidl根据界说的接口办法生成若干个TRANSACTION_<函数名> code常量,两头Binder经过这些code标识解析参数,调用架构师薪酬一月多少相应接口办法。换言之AIDL便是对BinderProxy.tra架构nsactBinder.onTransact进行了封装,运用者不用再自己界说每次通讯的cod链表排序e以及参数解析

跋文

本篇文章主要为不了解Bi宫颈癌前期症状nder系统架构师薪酬一月多少的读者供给一个抽象的知道,接下来的文章会从AIDL长途服务开始层层向下剖析整个IPC进程,所以假定想要更深一步了解Binder,本文作为前置知链表回转识也比较重要。

发表评论

提供最优质的资源集合

立即查看 了解详情