您的位置:首页 > 移动开发 > Android开发

【Android--Binder】关于通信机制之Binder机制(上)

2016-05-02 19:48 573 查看
Binder是什么?

Binder是什么?我们可以从字面上先去理解到,“粘合剂”,在很多情况下,我们使用Binder机制来实现Service和客户端的通信,例如当Activity和Service不在同一个进程下时,我们就可以通过使用Binder机制实现在不同进程下的通信。一句话概括为:Service-Client 的通信架构。

Binder机制的组成以及各自的职能?

在Binder机制下,Binder机制可以划分为:Client,Service,Service manager,Binder。

Client是客户功能模块。

Service 是服务功能模块。

Service Manager是服务管理模块。

Binder,它的职能和以上三种不同,没有直观的体现,而是一种“粘合剂”,更像一种桥梁,联通Service–Client通信。

下面引用下别人的图,感觉非常直观:



图中内容简单概括如下:

Client和Service 是在安卓应用程序中直接体现功能的,client和service直接通信属于(IPC  Inter-Process Communication 进程间通信)。

Client,Service和Service manager是属于用户空间的。Binder驱动属于内核空间。而open,ioctl两个是驱动程序中的操作函数。

Service Manager是一个守护进程,用来管理Service ,并向Client提供查询Server接口的能力。

(关于守护进程

在linux或者unix操作系统中在系统引导的时候会开启很多服务,这些服务就叫做守护进程。为了增加灵活性,root可以选择系统开启的模式,这些模式叫做运行级别,每一种运行级别以一定的方式配置系统。 守护进程是脱离于终端并且在后台运行的进程。守护进程脱离于终端是为了避免进程在执行过程中的信息在任何终端上显示并且进程也不会被任何终端所产生的终端信息所打断。



下面详细讲讲四个模块的职能以及部分工作原理:

Service manager

Service Manager属于守护进程,它在用户空间内。从字面就可以知道它的职能是管理Binder机制下的Service,所有在Binder机制下的Service都会在Service Manager有注册,包括Service的名称及内容都会包含在注册信息中,当Client需要接入某个Service时,Service Manager就会去寻找相应的Service。

Service manager 流程图

(引用下大神的图,感觉解释的很清楚)



对应图中的 main() 函数源码:

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;
}


注意上面源码中出现的三个函数:

1.Binder_open()

2.Binder_become_context_manager()

3.Binder_loop()

binder_open()函数用来打开设备文件。

Binder_become_context_manager(),运行到ioctl() 函数,得出结果,返回结果,验证是否是Binder上下文的管理者。

Binder_loop() 函数,可以简单的看出是一个含循环的函数。

调用Binder_loop()进入消息循环,等待Client的请求。如果没有Client请求,则进入中断等待状态;当有Client请求时,就被唤醒,然后读取并处理Client请求。

ServiceManager是如何启动的?

这里简要介绍一下ServiceManager的启动方式。当Kernel启动加载完驱动之后,会启动Android的init程序,init程序会解析init.rc,进而启动init.rc中定义的守护进程。而ServiceManager则正是通过注册在init.rc中,而被启动的。

下面是Binder_open源码:

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;
}


我们可以看看mmap() 函数中的参数。

mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0)

第一个参数是映射内存的起始地址,NULL代表让系统自动选定地址;mapsize大小是128*1024B,即128K;PROT_READ表示映射区域是可读的;MAP_PRIVATE表示建立一个写入时拷贝的私有映射,即,当进程中对该内存区域进行写入时,是写入到映射的拷贝中;bs->fd是”/dev/binder”句柄;而0表示偏移。

关于Service Manager更加详细的介绍,可以参考这里

Client

Client 操作流程

Service 在Service Manager内注册信息后,Client就可以通过“名字”去Binder那对相应的Service联系。例如以下流程场景:

Client申请“名字”为A的Binder的引用,Service Manager收到连接请求后,从原本的注册信息表中找到相应的Service,然后返回相应Service的Binder引用,对应的Client就会收到这个Binder引用。这是关于Client的简单介绍。

Service

关于Service方面是日常开发过程中非常普遍的,也是更容易接触到的,作为四大组件之一,在此不做太多介绍。

Binder 驱动

可以简单概括为:分别管理为Server端的Binder实体和Client端的引用。

Binder驱动原理及实现

以A,B两个不同进程为例,A进程如果要使用B进程的服务,B进程首先要注册此服务,A进程通过Binder获取该服务的handler,通过这个handler,A进程就可以使用该服务了。

关于Binder实现的参考文章,讲解挺详细
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息