溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Binder線程池工作過(guò)程是什么

發(fā)布時(shí)間:2022-03-25 09:32:10 來(lái)源:億速云 閱讀:359 作者:iii 欄目:互聯(lián)網(wǎng)科技

這篇文章主要介紹了Binder線程池工作過(guò)程是什么的相關(guān)知識(shí),內(nèi)容詳細(xì)易懂,操作簡(jiǎn)單快捷,具有一定借鑒價(jià)值,相信大家閱讀完這篇Binder線程池工作過(guò)程是什么文章都會(huì)有所收獲,下面我們一起來(lái)看看吧。

基于Android 6.0源碼剖析,分析Binder線程池以及binder線程啟動(dòng)過(guò)程。
Binder線程池工作過(guò)程是什么

一. 概述

Android系統(tǒng)啟動(dòng)完成后,ActivityManager, PackageManager等各大服務(wù)都運(yùn)行在system_server進(jìn)程,app應(yīng)用需要使用系統(tǒng)服務(wù)都是通過(guò)binder來(lái)完成進(jìn)程之間的通信,那對(duì)于binder線程是如何管理的呢,又是如何創(chuàng)建的呢?其實(shí)無(wú)論是system_server進(jìn)程,還是app進(jìn)程,都是在進(jìn)程fork完成后,便會(huì)在新進(jìn)程中執(zhí)行onZygoteInit()的過(guò)程中,啟動(dòng)binder線程池。接下來(lái),就以此為起點(diǎn)展開從線程的視角來(lái)看看binder的世界。

二. Binder線程創(chuàng)建

Binder線程創(chuàng)建與其所在進(jìn)程的創(chuàng)建中產(chǎn)生,Java層進(jìn)程的創(chuàng)建都是通過(guò)Process.start()方法,向Zygote進(jìn)程發(fā)出創(chuàng)建進(jìn)程的socket消息,Zygote收到消息后會(huì)調(diào)用Zygote.forkAndSpecialize()來(lái)fork出新進(jìn)程,在新進(jìn)程中會(huì)調(diào)用到RuntimeInit.nativeZygoteInit方法,該方法經(jīng)過(guò)jni映射,最終會(huì)調(diào)用到app_main.cpp中的onZygoteInit,那么接下來(lái)從這個(gè)方法說(shuō)起。

2.1 onZygoteInit

[-> app_main.cpp]

Binder線程池工作過(guò)程是什么

ProcessState::self()是單例模式,主要工作是調(diào)用open()打開/dev/binder驅(qū)動(dòng)設(shè)備,再利用mmap()映射內(nèi)核的地址空間,將Binder驅(qū)動(dòng)的fd賦值ProcessState對(duì)象中的變量mDriverFD,用于交互操作。startThreadPool()是創(chuàng)建一個(gè)新的binder線程,不斷進(jìn)行talkWithDriver()。

2.2 PS.startThreadPool

[-> ProcessState.cpp]

Binder線程池工作過(guò)程是什么

啟動(dòng)Binder線程池后, 則設(shè)置mThreadPoolStarted=true. 通過(guò)變量mThreadPoolStarted來(lái)保證每個(gè)應(yīng)用進(jìn)程只允許啟動(dòng)一個(gè)binder線程池, 且本次創(chuàng)建的是binder主線程(isMain=true). 其余binder線程池中的線程都是由Binder驅(qū)動(dòng)來(lái)控制創(chuàng)建的。

2.3 PS.spawnPooledThread

[-> ProcessState.cpp]

Binder線程池工作過(guò)程是什么

獲取Binder線程名,格式為Binder_x, 其中x為整數(shù)。每個(gè)進(jìn)程中的binder編碼是從1開始,依次遞增; 只有通過(guò)spawnPooledThread方法來(lái)創(chuàng)建的線程才符合這個(gè)格式,對(duì)于直接將當(dāng)前線程通過(guò)joinThreadPool加入線程池的線程名則不符合這個(gè)命名規(guī)則。 另外,目前Android N中Binder命令已改為Binder:_x格式, 則對(duì)于分析問(wèn)題很有幫忙.

2.3.2 PoolThread.run

[-> ProcessState.cpp]

Binder線程池工作過(guò)程是什么

  • 對(duì)于isMain=true的情況下, command為BC_ENTER_LOOPER,代表的是Binder主線程,不會(huì)退出的線程;

  • 對(duì)于isMain=false的情況下,command為BC_REGISTER_LOOPER,表示是由binder驅(qū)動(dòng)創(chuàng)建的線程。

2.5 processPendingDerefs

[-> IPCThreadState.cpp]

Binder線程池工作過(guò)程是什么

2.6 getAndExecuteCommand

[-> IPCThreadState.cpp]

Binder線程池工作過(guò)程是什么

2.7 talkWithDriver

Binder線程池工作過(guò)程是什么

在這里調(diào)用的isMain=true,也就是向mOut例如寫入的便是BC_ENTER_LOOPER. 經(jīng)過(guò)talkWithDriver(), 接下來(lái)程序往哪進(jìn)行呢?從binder_thread_write()往下說(shuō)BC_ENTER_LOOPER的處理過(guò)程。
2.7.1 binder_thread_write

[-> binder.c]

Binder線程池工作過(guò)程是什么

Binder線程池工作過(guò)程是什么

Binder線程池工作過(guò)程是什么

Binder線程池工作過(guò)程是什么

當(dāng)發(fā)生以下3種情況之一,便會(huì)進(jìn)入done:

  • 當(dāng)前線程的return_error發(fā)生錯(cuò)誤的情況;

  • 當(dāng)Binder驅(qū)動(dòng)向客戶端發(fā)送死亡通知的情況;

  • 當(dāng)類型為BINDER_WORK_TRANSACTION(即收到命令是BC_TRANSACTION或BC_REPLY)的情況;

任何一個(gè)Binder線程當(dāng)同時(shí)滿足以下條件,則會(huì)生成用于創(chuàng)建新線程的BR_SPAWN_LOOPER命令:

  1. 當(dāng)前進(jìn)程中沒(méi)有請(qǐng)求創(chuàng)建binder線程,即requested_threads = 0;

  2. 當(dāng)前進(jìn)程沒(méi)有空閑可用的binder線程,即ready_threads = 0;(線程進(jìn)入休眠狀態(tài)的個(gè)數(shù)就是空閑線程數(shù))

  3. 當(dāng)前進(jìn)程已啟動(dòng)線程個(gè)數(shù)小于最大上限(默認(rèn)15);

  4. 當(dāng)前線程已接收到BC_ENTER_LOOPER或者BC_REGISTER_LOOPER命令,即當(dāng)前處于BINDER_LOOPER_STATE_REGISTERED或者BINDER_LOOPER_STATE_ENTERED狀態(tài)?!拘」?jié)2.6】已設(shè)置狀態(tài)為BINDER_LOOPER_STATE_ENTERED,顯然這條件是滿足的。

從system_server的binder線程一直的執(zhí)行流:IPC.joinThreadPool - > IPC.getAndExecuteCommand() - > IPC.talkWithDriver(),但talkWithDriver收到事務(wù)之后,便進(jìn)入IPC.executeCommand(),接下來(lái),從executeCommand說(shuō)起。

2.8 IPC.executeCommand

Binder線程池工作過(guò)程是什么

Binder主線程的創(chuàng)建是在其所在的進(jìn)程創(chuàng)建的過(guò)程一起創(chuàng)建的,后面再創(chuàng)建的普通binder線程是由spawnPooledThread(false)方法所創(chuàng)建的。

2.9思考

默認(rèn)地,每個(gè)進(jìn)程的binder線程池的線程個(gè)數(shù)上限為15,該上限不統(tǒng)計(jì)通過(guò)BC_ENTER_LOOPER命令創(chuàng)建的binder主線程,只計(jì)算BC_REGISTER_LOOPER命令創(chuàng)建的線程對(duì)此,或者很多人不理解,例栗子:某個(gè)進(jìn)程的主線程執(zhí)行如下方法,那么該進(jìn)程可創(chuàng)建的binder線程個(gè)數(shù)上限是多少呢?

Binder線程池工作過(guò)程是什么

首先線程池的binder線程個(gè)數(shù)上限為6個(gè),通過(guò)startThreadPool()創(chuàng)建的主線程不在最大線程上限,最后一句是將當(dāng)前線程成為binder線程,所以說(shuō)可創(chuàng)建的binder線程個(gè)數(shù)上限為8 ,如果還不理解,建議再多看看這幾個(gè)方案的源碼,多思考整個(gè)binder架構(gòu)。

三??偨Y(jié)

Binder設(shè)計(jì)架構(gòu)中,只有第一個(gè)Binder主線程(也就是Binder_1線程)是由應(yīng)用程序主動(dòng)創(chuàng)建,Binder線程池的普通線程都是由Binder驅(qū)動(dòng)根據(jù)IPC通信需求創(chuàng)建,Binder線程的創(chuàng)建流程圖:

Binder線程池工作過(guò)程是什么

每次由Zygote fork出新進(jìn)程的過(guò)程中,伴隨著創(chuàng)建binder線程池,調(diào)用spawnPooledThread來(lái)創(chuàng)建binder主線程。當(dāng)線程執(zhí)行binder_thread_read的過(guò)程中,發(fā)現(xiàn)當(dāng)前沒(méi)有空閑線程,沒(méi)有請(qǐng)求創(chuàng)建線程,且沒(méi)有達(dá)到上限,則創(chuàng)建新的binder線程。

Binder的交易有3種類型:

  1. 調(diào)用:發(fā)起進(jìn)程的線程不一定是在Binder線程,大多數(shù)情況下,接收者只指向進(jìn)程,并不確定會(huì)有哪個(gè)線程來(lái)處理,所以不指定線程;

  2. 答復(fù):發(fā)起者一定是binder線程,并且接收者線程便是上次call時(shí)的發(fā)起線程(該線程不一定是binder線程,可以是任意線程)。

  3. async:與調(diào)用類型差不多,唯一不同的是async是oneway方式不需要回復(fù),發(fā)起進(jìn)程的線程不一定是在Binder線程,接收者只指向進(jìn)程,并且不確定會(huì)有哪個(gè)線程來(lái)處理,所以不指定線程。

Binder系統(tǒng)中可分為3類binder線程:

  • Binder主線程:進(jìn)程創(chuàng)建過(guò)程會(huì)調(diào)用startThreadPool()過(guò)程中再進(jìn)入spawnPooledThread(true),來(lái)創(chuàng)建Binder主線程。編號(hào)從1開始,也就是意味著binder主線程名為binder_1,并且主線程是不會(huì)退出的。

  • Binder普通線程:是由Binder Driver來(lái)根據(jù)是否有空閑的binder線程來(lái)決定是否創(chuàng)建binder線程,回調(diào)spawnPooledThread(false),isMain = false,該線程名格式為binder_x。

  • Binder其他線程其他線程是指并沒(méi)有調(diào)用spawnPooledThread方法,而是直接調(diào)用IPC.joinThreadPool(),將當(dāng)前線程直接加入binder線程隊(duì)列。例如:mediaserver和servicemanager的主線程都是binder線程,但system_server的主線程并非binder線程。

關(guān)于“Binder線程池工作過(guò)程是什么”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對(duì)“Binder線程池工作過(guò)程是什么”知識(shí)都有一定的了解,大家如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI