android 共享内存 ioctl,Android进程间通信--碎碎念

感谢邓凡平老师的《深入理解Android系统》,这篇文章就是看完邓老师的第六章深入理解Binder 后的碎碎念。

Binder是什么?

Binder是Android进程间通信机制,就像共享内存,共享文件等一样,是一套IPC的机制;

Android的Binder机制是在OpenBinder开源项目实现的;

Binder机制是一个C/S的通信架构

相比于其他IPC的优势?

更好的传输性能

SOCKET:是一个通用接口,导致其传输效率低,开销大;

管道和消息队列:因为采用存储转发方式,所以至少需要拷贝2次数据,效率低;

共享内存:虽然在传输时没有拷贝数据,但其控制机制复杂;

更高的安全性

Binder机制的UID/PID是由Binder机制本身在内核空间添加身份标识,安全性高;

Binder可以建立私有通道,这是linux的通信机制所无法实现的;

Binder的整体架构:

0818b9ca8b590ca3270a3433284dd417.png

从图中我们可以看出:

1)IPC指的是Client和Server模块之间的通信,虚线的双向箭头表示实际的数据并非Client、Server间直接传递,而是通过实线箭头传递的;

2)Client通过open、ioctl两个方法将自己需要通信的数据传入底层BinderDriver中,Server端通过open和ioctl获取Client写入BinderDriver中的数据,然后处理并再次通过Driver返回给Client;

3)ServiceManager,Binder中的老大,不负责具体通信工作,负责管理Server;

4)Binder机制实际上是虚拟了一个Binder设备,放在/dev/目录下,Client和Server通过访问BinderDriver实现互相之间的通信。

图中所能看到的问题:

1) Service Manager有什么用?

Binder通信中的老大,管理Server,系统中每个进程(Client和Server)都知道ServiceManager的位置,Server要提供服务,需要在ServiceManager中注册,Client需要什么服务需要向ServeiceManager要,这样Client和Server两端才能取得联系,互相通信;

2)Client/Server之间怎么通信的?

接下来通过一个MediaPlayerService的启动过程分析;

3)open/ioctl 做了什么?

open和ioctl是Linux驱动编程的方法,用来访问驱动程序

Client/Server之间怎么通信的?

通过MediaPlayerService的启动过程来分析Client和Server之间是怎么通信的;

// MediaPlayService 启动main函数

int main(int argc, char** argv) {

1) spproc(ProcessState::self());

2)spsm = defaultServiceManager();

3) AudioFlinger::instantiate(); MediaPlayService::instantiate();CameraService::instantiate(); AudioPolicyService::instantiate();

4)ProcessState::self()->startThreadPool();

5)IPCThreadState::self()->joinThreadPool();

}

整个的启动分为5个部分

1 实例化一个ProcessState

2 获取一个IServiceManager对象

3 各种实例化

4 开启一个线程池

5 当前线程调用一个joinThreadPool()方法

新的问题:

1 ProcessState有什么作用?

2 IPCThreadState有什么作用?

3 IserviceManager明显是个借口or抽象类,具体的对象是什么?

4 实例化(第三部分)都坐了那些操作

ProcessState

单例模式,并且在构造函数中打开了Binder设备,也就是说:

1)每个进程中只有一个ProcessState对象

2)只打开了一次Binder设备

defaultServiceManager()的返回

启动过程中的第二部分,获取一个IServiceManager对象,

defaultServiceManager();

{

……

return interface_cast(ProcessState::self()->getContextObject(NULL));}

//ProcessState::self()->getContextObject(NULL)

spProcessState::getContextObject(const sp& caller)

{

……

return getStrongProxyForHandle(0);

}

//getStrongProxyForHandle(0);

spProcessState::getStrongProxyForHandle( inte32_t handler)

{……、

return new BpBinder(handle);

}

从上面的代码看到两类Binder和IServiceManager,这是两个大的“家族”。

Binder家族

0818b9ca8b590ca3270a3433284dd417.png

BpBinder—Client端的对象

BBinder—Server端的对象

BpBinder和BBinder是一一对应的

Server家族

Binder机制里每个Server都要符合这样的家族“族谱”:

0818b9ca8b590ca3270a3433284dd417.png

其中的XXX就指具体的服务,在Binder中ServiceManager也是个Server,应该有自己的有IserviceManager;{defaultServiceManager所获取的那个对象}

再返回代码defaultServiceManager代码中,由interface_cast的实现可以发现,IServiceManager通过宏定义实现了一个BpServiceManager;

return interface_cast

(ProcessState::self()->getContextObject(NULL))

#define IMPLEMENT_META_INTERFACE(INTERFACE,NAME)

……

if (intr == NULL) {

intr = newBp##INTERFACE(obj);

}

其中INTERFACE就是每个Server的名称,在此处为ServiceManager,会生返回一个BpServiceManager对象。

IServiceManager的方法:

virtual sp getService(constString16& name)

获取一个Service

virtual sp checkService(const String16& name)

检查一个Service

virtual status_t addService(constString16& name, const sp& service)

想ServiceManager中添加一个Service

virtual VectorlistServices()

获取ServiceManager管理的所有可用的Service

第三步:instantiate/实例化

以MediaPlayerService为例:

defaultServiceManager()->addService(String16(“media.player”),newMediaPlayerService());

只有一句话,想Servicemanager中添加一个Service,具体的添加实现会调用到

BpBinder()->transact();而该方法最终会执行下面的代码IPCThreadState()->transact();

再看IPCThreadState:

特点:每个线程有一个;Service支持多线程;

功能:transact();handle,发送,循环等待;

重点:talkWithDriver();

Ipcthreadstate的transact方法是一个发送和循环等待的逻辑,也就是实际的交互逻辑;

最终的交互方法是talkWithDriver(),与BinderDriver交互,获取和写入数据。

最后两步骤:

4) ProcessState::self()->startThreadPool();

开启线程池,将每个线程的IPCThreadState对象都调用一下joinThreadPool();

5) IPCThreadState::self()->joinThreadPool();

本身也调用一下joinThreadPool()——>talkWithDriver();

joinThreadPool最终也会talkWithDriver,等待Driver给自己消息,然后提供服务。

ServiceManager.c

ServiceManager在binder 架构中提供管理Server的服务,也是一个Server,前面可见其有IServiceManager和bpServiceManager,应该有对应的bnserviceManager 但是巡边源码都找不到;

确实有代码实现了bnServiceManager应该实现的服务,也就在上页中介绍的内容,在service_manager.c文件中,实现了bnServiceManager的功能。

//ServiceManager的启动过程

intmain(int argc, char **argv) {

structbinder_state *bs;

void*svcmgr = BINDER_SERVICE_MANAGER;

bs =binder_open(128 * 1024);

if(binder_become_context_manager(bs)) {

LOGE("cannotbecome context manager (%s)\n", strerror(errno));

return-1;

}

svcmgr_handle= svcmgr;

binder_loop(bs,svcmgr_handler);

return0;

}

Svcmgr_handler是个函数指针,其具体实现了addservice,checkservice,getservice,listservices。

两个疑点解惑:

BBinder:Server的实现确实需要遵循Server大家族结构,以F热管Service为例:FregService—>BnFregService->BnInterface->BBinder,其中的à表示继承关系。

确实没有BnServiceManager。

没有涉及到的:

open/ioctl

servicemanager提供的其他服务

实现一个服务native、aidl(AndroidInterface definition language)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值