一. 概述
创新互联公司10多年企业网站制作服务;为您提供网站建设,网站制作,网页设计及高端网站定制服务,企业网站制作及推广,对发电机维修等多个方面拥有多年的营销推广经验的网站建设公司。
Android系统启动完成后,ActivityManager, PackageManager等各大服务都运行在system_server进程,app应用需要使用系统服务都是通过binder来完成进程之间的通信,那对于binder线程是如何管理的呢,又是如何创建的呢?其实无论是system_server进程,还是app进程,都是在进程fork完成后,便会在新进程中执行onZygoteInit()的过程中,启动binder线程池。接下来,就以此为起点展开从线程的视角来看看binder的世界。
二. Binder线程创建
Binder线程创建与其所在进程的创建中产生,Java层进程的创建都是通过Process.start()方法,向Zygote进程发出创建进程的socket消息,Zygote收到消息后会调用Zygote.forkAndSpecialize()来fork出新进程,在新进程中会调用到RuntimeInit.nativeZygoteInit方法,该方法经过jni映射,最终会调用到app_main.cpp中的onZygoteInit,那么接下来从这个方法说起。
1. onZygoteInit
- [-> app_main.cpp]
ProcessState::self()是单例模式,主要工作是调用open()打开/dev/binder驱动设备,再利用mmap()映射内核的地址空间,将Binder驱动的fd赋值ProcessState对象中的变量mDriverFD,用于交互操作。startThreadPool()是创建一个新的binder线程,不断进行talkWithDriver()。
2. PS.startThreadPool
- [-> ProcessState.cpp]
启动Binder线程池后, 则设置mThreadPoolStarted=true. 通过变量mThreadPoolStarted来保证每个应用进程只允许启动一个binder线程池, 且本次创建的是binder主线程(isMain=true). 其余binder线程池中的线程都是由Binder驱动来控制创建的。
3. PS.spawnPooledThread
- [-> ProcessState.cpp]
(1) makeBinderThreadName
- [-> ProcessState.cpp]
获取Binder线程名,格式为Binder_x, 其中x为整数。每个进程中的binder编码是从1开始,依次递增; 只有通过spawnPooledThread方法来创建的线程才符合这个格式,对于直接将当前线程通过joinThreadPool加入线程池的线程名则不符合这个命名规则。 另外,目前Android N中Binder命令已改为Binder:_x格式, 则对于分析问题很有帮忙.
(2) PoolThread.run
- [-> ProcessState.cpp]
从函数名看起来是创建线程池,其实就只是创建一个线程,该PoolThread继承Thread类。t->run()方法最终调用 PoolThread的threadLoop()方法。
4. IPC.joinThreadPool
- [-> IPCThreadState.cpp]
5. processPendingDerefs
- [-> IPCThreadState.cpp]
6. getAndExecuteCommand
- [-> IPCThreadState.cpp]
7. talkWithDriver
在这里调用的isMain=true,也就是向mOut例如写入的便是BC_ENTER_LOOPER. 经过talkWithDriver(), 接下来程序往哪进行呢?从binder_thread_write()往下说BC_ENTER_LOOPER的处理过程。
(1) binder_thread_write
- [-> binder.c]
当发生以下3种情况之一,便会进入done:
任何一个Binder线程当同时满足以下条件,则会生成用于创建新线程的BR_SPAWN_LOOPER命令:
从system_server的binder线程一直的执行流:IPC.joinThreadPool - > IPC.getAndExecuteCommand() - > IPC.talkWithDriver(),但talkWithDriver收到事务之后,便进入IPC.executeCommand(),接下来,从executeCommand说起。
8. IPC.executeCommand
Binder主线程的创建是在其所在的进程创建的过程一起创建的,后面再创建的普通binder线程是由spawnPooledThread(false)方法所创建的。
9. 思考
默认地,每个进程的binder线程池的线程个数上限为15,该上限不统计通过BC_ENTER_LOOPER命令创建的binder主线程,只计算BC_REGISTER_LOOPER命令创建的线程对此,或者很多人不理解,例栗子:某个进程的主线程执行如下方法,那么该进程可创建的binder线程个数上限是多少呢?
首先线程池的binder线程个数上限为6个,通过startThreadPool()创建的主线程不在***线程上限,***一句是将当前线程成为binder线程,所以说可创建的binder线程个数上限为8 ,如果还不理解,建议再多看看这几个方案的源码,多思考整个binder架构。
三、总结
Binder设计架构中,只有***个Binder主线程(也就是Binder_1线程)是由应用程序主动创建,Binder线程池的普通线程都是由Binder驱动根据IPC通信需求创建,Binder线程的创建流程图:
每次由Zygote fork出新进程的过程中,伴随着创建binder线程池,调用spawnPooledThread来创建binder主线程。当线程执行binder_thread_read的过程中,发现当前没有空闲线程,没有请求创建线程,且没有达到上限,则创建新的binder线程。
1. Binder的交易有3种类型:
2. Binder系统中可分为3类binder线程:
【本文是专栏“小米开放平台”原创文章,“小米开放平台”微信公众号xiaomideveloper】
网页题目:进程的Binde线程池工作过程
URL网址:http://www.shufengxianlan.com/qtweb/news46/308346.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联