当前位置:首页 > 经验 >

android binder机制面试题(android面试开发中遇到的难点)

来源:原点资讯(www.yd166.com)时间:2022-11-01 07:27:44作者:YD166手机阅读>>

Binder一次拷贝原理

4. 系统服务与bindService等启动的服务的区别

服务可分为系统服务与普通服务,系统服务一般是在系统启动的时候,由SystemServer进程创建并注册到ServiceManager中的。而普通服务一般是通过ActivityManagerService启动的服务,或者说通过四大组件中的Service组件启动的服务。这两种服务在实现跟使用上是有不同的,主要从以下几个方面:

  • 服务的启动方式

  • 服务的注册与管理

  • 服务的请求使用方式

首先看一下服务的启动上,系统服务一般都是SystemServer进程负责启动,比如AMS,WMS,PKMS,电源管理等,这些服务本身其实实现了Binder接口,作为Binder实体注册到ServiceManager中,被ServiceManager管理,而SystemServer进程里面会启动一些Binder线程,主要用于监听Client的请求,并分发给响应的服务实体类,可以看出,这些系统服务是位于SystemServer进程中(有例外,比如Media服务)。在来看一下bindService类型的服务,这类服务一般是通过ActivitystartService或者其他contextstartService启动的,这里的Service组件只是个封装,主要的是里面Binder服务实体类,这个启动过程不是ServcieManager管理的,而是通过ActivityManagerService进行管理的,同Activity管理类似。

再来看一下服务的注册与管理:系统服务一般都是通过ServiceManager的addService进行注册的,这些服务一般都是需要拥有特定的权限才能注册到ServiceManager,而bindService启动的服务可以算是注册到ActivityManagerService,只不过ActivityManagerService管理服务的方式同ServiceManager不一样,而是采用了Activity的管理模型,详细的可以自行分析。

最后看一下使用方式,使用系统服务一般都是通过ServiceManagergetService得到服务的句柄,这个过程其实就是去ServiceManager中查询注册系统服务。而bindService启动的服务,主要是去ActivityManagerService中去查找相应的Service组件,最终会将Service内部Binder的句柄传给Client。

android binder机制面试题,android面试开发中遇到的难点(5)

系统服务与bindService启动服务的区别

5. Binder线程、Binder主线程、Client请求线程的概念与区别

Binder线程是执行Binder服务的载体,只对于服务端才有意义,对请求端来说,是不需要考虑Binder线程的,但Android系统的处理机制其实大部分是互为C/S的。比如APP与AMS进行交互的时候,都互为对方的C与S,这里先不讨论这个问题,先看Binder线程的概念。

Binder线程就是执行Binder实体业务的线程,一个普通线程如何才能成为Binder线程呢?很简单,只要开启一个监听Binder字符设备的Loop线程即可,在Android中有很多种方法,不过归根到底都是监听Binder,换成代码就是通过ioctl来进行监听。

拿ServerManager进程来说,其主线就是Binder线程,其做法是通过binder_loop实现不死线程:

void binder_loop(struct binder_state *bs, binder_handler func)
{
...
for (;;) {
<!--关键点1-->
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
<!--关键点2-->
res = binder_parse(bs, 0, readbuf, bwr.read_consumed, func);
。。
}
}

上面的关键代码1就是阻塞监听客户端请求,2 就是处理请求,并且这是一个死循环,不退出。再来看SystemServer进程中的线程,在Android4.3(6.0以后打代码就不一样了)中SystemSever主线程便是Binder线程,同时一个Binder主线程。

Binder线程与Binder主线程的区别是:线程是否可以终止Loop,不过目前启动的Binder线程都是无法退出的,其实可以全部看做是Binder主线程,其实现原理是,在SystemServer主线程执行到最后的时候,Loop监听Binder设备,变身死循环线程,关键代码如下:

extern "C" status_t system_init
{
...
ALOGI("System server: entering thread pool.\n");
ProcessState::self->startThreadPool;
IPCThreadState::self->joinThreadPool;
ALOGI("System server: exiting thread pool.\n");
return NO_ERROR;
}

ProcessState::self->startThreadPool是新建一个Binder主线程,而PCThreadState::self->joinThreadPool是将当前线程变成Binder主线程。其实startThreadPool最终也会调用joinThreadPool,看下其关键函数:

void IPCThreadState::joinThreadPool(bool isMain)
{
...
status_t result;
do {
int32_t cmd;
...关键点1
result = talkWithDriver;
if (result >= NO_ERROR) {
...关键点2
result = executeCommand(cmd);
}
// 非主线程的可以退出
if(result == TIMED_OUT && !isMain) {
break;
}
// 死循环,不完结,调用了这个,就好比是开启了Binder监听循环,
} while (result != -ECONNREFUSED && result != -EBADF);
}

status_t IPCThreadState::talkWithDriver(bool doReceive)
{
do {
...关键点3
if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
}

先看关键点1 talkWithDriver,其实质还是去掉用ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)去不断的监听Binder字符设备,获取到Client传输的数据后,再通过executeCommand去执行相应的请求,joinThreadPool是普通线程化身Binder线程最常见的方式。不信,就再看一个MediaService,看一下main_mediaserver的main函数:

int main(int argc, char** argv)
{
。。。
sp<ProcessState> proc(ProcessState::self);
sp<IServiceManager> sm = defaultServiceManager;
ALOGI("ServiceManager: %p", sm.get);
AudioFlinger::instantiate;
MediaPlayerService::instantiate;
CameraService::instantiate;
AudioPolicyService::instantiate;
registerExtensions;
ProcessState::self->startThreadPool;
IPCThreadState::self->joinThreadPool;
}

其实还是通过joinThreadPool变身Binder线程,至于是不是主线程,看一下下面的函数:

void IPCThreadState::joinThreadPool(bool isMain)

void ProcessState::spawnPooledThread(bool isMain)
{
if (mThreadPoolStarted) {
String8 name = makeBinderThreadName;
ALOGV("Spawning new pooled thread, name=%s\n", name.string);
sp<Thread> t = new PoolThread(isMain);
t->run(name.string);
}
}

其实关键就是就是传递给joinThreadPool函数的isMain是否是true,不过是否是Binder主线程并没有什么用,因为源码中并没有为这两者的不同处理留入口,感兴趣可以去查看一下binder中的TIMED_OUT。

最后来看一下普通Clientbinder请求线程,比如我们APP的主线程,在startActivity请求AMS的时候,APP的主线程成其实就是Binder请求线程,在进行Binder通信的过程中,Client的Binder请求线程会一直阻塞,知道Service处理完毕返回处理结果。

本文先讲到这里,内容比较多,多看看多理解。

android binder机制面试题,android面试开发中遇到的难点(6)

近期文章:

  • 详解Android 9.0私有API禁用机制

  • Bitmap与OOM的爱恨情仇

  • 面试必问:Android Handler机制之ThreadLocal

今日问题:

Binder机制里有哪些难理解的点?

打卡格式:

打卡 X 天,答:xxx 。

android binder机制面试题,android面试开发中遇到的难点(7)

,
上一页12末页

栏目热文

android 开发教程(android开发详细教程)

android 开发教程(android开发详细教程)

安卓(Android)是一种基于Linux的自由及开放源代码的操作系统。主要使用于移动设备,如智能手机和平板电脑。之前有...

2022-11-01 06:53:06查看全文 >>

android新手教程(android基础知识)

android新手教程(android基础知识)

写在前面:一名正在学习中的女程序员(欢迎大家关注我 ~期待和大家一起交流和学习Android的相关知识)本人也是众多An...

2022-11-01 07:16:59查看全文 >>

android开发手册(android学习手册)

android开发手册(android学习手册)

前言无规矩不成方圆,无规范不能协作。阿里近万名Java技术精英的经验总结,铸就了高含金量的《阿里巴巴Android开发手...

2022-11-01 07:09:10查看全文 >>

张甸划到高港区了吗(张甸明年拆迁地段在哪)

张甸划到高港区了吗(张甸明年拆迁地段在哪)

喜讯!!!近日《2021年中国中小城市高质量发展指数研究成果》发布揭晓了2021年全国综合实力百强县市全国综合实力百强区...

2022-11-01 07:34:15查看全文 >>

张士村高铁经过路线(张桂高铁经过)

张士村高铁经过路线(张桂高铁经过)

2019年,沈阳城建计划投资规模超300亿元,将围绕完善交通设施建设、突出生态环境建设、统筹公用设施建设、加强补齐民生...

2022-11-01 07:22:25查看全文 >>

android基础教程学习(android学习手册)

android基础教程学习(android学习手册)

您可以使用 Kotlin、Java 和 C 语言编写 Android 应用。Android SDK 工具会将您的代码...

2022-11-01 07:22:41查看全文 >>

android经典简单小项目(android 项目图解)

android经典简单小项目(android 项目图解)

《开源精选》是我们分享Github、Gitee等开源社区中优质项目的栏目,包括技术、学习、实用与各种有趣的内容。本期推荐...

2022-11-01 06:54:13查看全文 >>

新手android教程(android菜鸟教程)

新手android教程(android菜鸟教程)

许多人对Android开发很感兴趣,于是想自己自学Android开发这门技术,对于想入门这个行业或者是作为兴趣的人。一开...

2022-11-01 07:12:01查看全文 >>

android高级面试题及答案(android面试题目及最佳答案)

android高级面试题及答案(android面试题目及最佳答案)

(1)JAVA面试题(基础 进阶)(必须)java中==和equals和hashcode的区别==是运算符,用来比较两个...

2022-11-01 07:32:30查看全文 >>

android实战技巧(android入门图解)

android实战技巧(android入门图解)

前言随着互联网的发展,高可靠、高并发以及降本增效,已成为各大公司面临的现实挑战,性能优化需求愈发迫切, 大到系统,小到代...

2022-11-01 07:04:23查看全文 >>

文档排行