自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

進(jìn)程的Binde線程池工作過程

開發(fā) 開發(fā)工具
本文基于Android 6.0源碼剖析,分析Binder線程池以及binder線程啟動過程。

進(jìn)程的Binde線程池工作過程

一. 概述

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

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

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

1. onZygoteInit

 

  1. [-> app_main.cpp] 

onZygoteInit

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

2. PS.startThreadPool

  1. [-> ProcessState.cpp] 

PS.startThreadPool

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

3. PS.spawnPooledThread

  1. [-> ProcessState.cpp] 

(1) makeBinderThreadName

  1. [-> ProcessState.cpp] 

makeBinderThreadName

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

(2) PoolThread.run

  1. [-> ProcessState.cpp] 

PoolThread.run

從函數(shù)名看起來是創(chuàng)建線程池,其實(shí)就只是創(chuàng)建一個線程,該P(yáng)oolThread繼承Thread類。t->run()方法最終調(diào)用 PoolThread的threadLoop()方法。

4. IPC.joinThreadPool

  1. [-> IPCThreadState.cpp] 

IPC.joinThreadPool

  • 對于isMain=true的情況下, command為BC_ENTER_LOOPER,代表的是Binder主線程,不會退出的線程;
  • 對于isMain=false的情況下,command為BC_REGISTER_LOOPER,表示是由binder驅(qū)動創(chuàng)建的線程。

5. processPendingDerefs

  1. [-> IPCThreadState.cpp] 

processPendingDerefs

6. getAndExecuteCommand

  1. [-> IPCThreadState.cpp] 

2.6 getAndExecuteCommand

7. talkWithDriver

7. talkWithDriver

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

(1) binder_thread_write

  1. [-> binder.c] 

binder_thread_write

binder_thread_write

binder_thread_write

binder_thread_write

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

  • 當(dāng)前線程的return_error發(fā)生錯誤的情況;
  • 當(dāng)Binder驅(qū)動向客戶端發(fā)送死亡通知的情況;
  • 當(dāng)類型為BINDER_WORK_TRANSACTION(即收到命令是BC_TRANSACTION或BC_REPLY)的情況;

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

  • 當(dāng)前進(jìn)程中沒有請求創(chuàng)建binder線程,即requested_threads = 0;
  • 當(dāng)前進(jìn)程沒有空閑可用的binder線程,即ready_threads = 0;(線程進(jìn)入休眠狀態(tài)的個數(shù)就是空閑線程數(shù))
  • 當(dāng)前進(jìn)程已啟動線程個數(shù)小于***上限(默認(rèn)15);
  • 當(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(),接下來,從executeCommand說起。

8. IPC.executeCommand

IPC.executeCommand

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

9. 思考

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

進(jìn)程可創(chuàng)建的binder線程個數(shù)上限是多少

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

三、總結(jié)

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

Binder線程的創(chuàng)建流程圖

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

1. Binder的交易有3種類型:

  • 調(diào)用:發(fā)起進(jìn)程的線程不一定是在Binder線程,大多數(shù)情況下,接收者只指向進(jìn)程,并不確定會有哪個線程來處理,所以不指定線程;
  • 答復(fù):發(fā)起者一定是binder線程,并且接收者線程便是上次call時的發(fā)起線程(該線程不一定是binder線程,可以是任意線程)。
  • async:與調(diào)用類型差不多,唯一不同的是async是oneway方式不需要回復(fù),發(fā)起進(jìn)程的線程不一定是在Binder線程,接收者只指向進(jìn)程,并且不確定會有哪個線程來處理,所以不指定線程。

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

  • Binder主線程:進(jìn)程創(chuàng)建過程會調(diào)用startThreadPool()過程中再進(jìn)入spawnPooledThread(true),來創(chuàng)建Binder主線程。編號從1開始,也就是意味著binder主線程名為binder_1,并且主線程是不會退出的。
  • Binder普通線程:是由Binder Driver來根據(jù)是否有空閑的binder線程來決定是否創(chuàng)建binder線程,回調(diào)spawnPooledThread(false),isMain = false,該線程名格式為binder_x。
  • Binder其他線程其他線程是指并沒有調(diào)用spawnPooledThread方法,而是直接調(diào)用IPC.joinThreadPool(),將當(dāng)前線程直接加入binder線程隊(duì)列。例如:mediaserver和servicemanager的主線程都是binder線程,但system_server的主線程并非binder線程。

【本文是51CTO專欄“小米開放平臺”原創(chuàng)文章,“小米開放平臺”微信公眾號xiaomideveloper】

戳這里,看該作者更多好文

責(zé)任編輯:趙寧寧 來源: 51CTO.com
相關(guān)推薦

2010-09-01 15:17:04

DHCP工作過程

2009-02-24 09:48:00

IP電話語音數(shù)據(jù)

2014-06-03 17:29:48

PPP路由器

2010-09-01 15:37:04

DHCP工作過程

2010-08-30 11:28:53

DHCP工作過程

2010-03-19 13:50:48

三層交換機(jī)

2010-01-06 11:30:22

.NET Framew

2017-01-10 13:39:57

Python線程池進(jìn)程池

2013-03-04 09:56:20

網(wǎng)絡(luò)管理員路由器路由工作原理

2021-07-16 11:35:20

Java線程池代碼

2011-12-26 14:07:07

游戲

2011-02-24 14:23:18

2024-07-15 08:20:24

2024-03-11 18:18:58

項(xiàng)目Spring線程池

2024-11-27 08:15:50

2020-10-22 09:35:11

線程池核心線程阻塞隊(duì)列

2018-07-05 14:18:12

數(shù)據(jù)分析神經(jīng)網(wǎng)絡(luò)模型

2021-03-08 08:55:22

開發(fā)

2010-06-22 15:51:38

Autoconf rp

2009-08-25 15:48:03

C#數(shù)組操作
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號