#### **參考文章**:
[深入了解Android系統之系統開篇](http://www.hmoore.net/alex_wsc/androidsystem/403521)
[Google官方AndroidAPI指南之線程和進程](http://www.hmoore.net/alex_wsc/android_google/488784)
[進程線程](http://note.youdao.com/noteshare?id=de140840a1da668b7f2f7f3facb34620)
[Android多線程的四種方式](http://mp.weixin.qq.com/s/Gv600dQgjqx5gQNM5_nm7Q)
[android 中 任務、進程和線程的區別](https://www.2cto.com/kf/201606/518400.html)
關于進程中知識,可以參考Git袁大神的博客,鄙人整理的文章[進程](http://www.hmoore.net/alex_wsc/androidsystem/403689)
如何查看手機中運行的進程,參考一下文章:
可以通過命令,也可以通過工具(DDMS、Android Device Monitor):
[android查看當前手機中的進程](http://blog.csdn.net/dfskhgalshgkajghljgh/article/details/51373694)
[adb 查看手機正在運行的進程](http://blog.csdn.net/xingchenxuanfeng/article/details/50386689)
[Android中使用ps命令查看進程PID](http://blog.csdn.net/yin1031468524/article/details/60772562)
[查看android進程信息](http://blog.csdn.net/ynnmnm/article/details/38417829)
[在Android Studio中使用Method trace,查看某進程的所有線程trace的方法 ](https://segmentfault.com/a/1190000011084104)
下圖是使用AS在它的終端欄使用`adb shell ps` 命令得到系統中存在的進程
:-: 
圖1 手機中的進程信息
各列參數意義:
* USER ? ? ? ?進程當前用戶;
* PID ? ? ? ? ? ? Process ID,進程ID;
* PPID ? ? ? ? ?Process Parent ID,進程的父進程ID;
* VSIZE ? ? ? ?Virtual Size,進程的虛擬內存大小;
* RSS ? ? ? ? ??Resident Set Size,實際駐留"在內存中"的內存大小;
* WCHAN ? ?休眠進程在內核中的地址;
* PC ? ? ? ? ? ? ?Program Counter;
* NAME ? ? ? ?進程名;
**可以跟findstr結合搜索,過濾得到自己想要找的進程**,如
~~~
adb shell ps | findstr sina
~~~
:-: 
圖 2 過濾手機中的進程信息
### **進程**
我們以進程的角度來看一下系統啟動流程:
[點擊查看大圖](https://box.kancloud.cn/dfd42ed393f8add8418c5ff6d994b7ff_2904x1536.jpg)
:-: 
圖3 系統啟動架構圖
>[info] **注意**:上圖我們是以**Android6.0源碼**為準則來研究Android的系統架構,如果是其它版本的源碼,流程可能會有細微差別,比如Android4.4W(API 20)以及其以下版本中的流程可能就會不一樣,可能是因為Android虛擬機由Dalvik轉換成Android Runtime,這一點還有待驗證。
#### **Android系統的啟動過程**
>[warning] 注意:以Android2.3.7(API 10)源碼來研究啟動流程
Android系統的啟動分為3個步驟:
1. Linux啟動:
* BootLoader
嵌入式系統的一個引導程序
* Kernel
驅動在這一層啟動
2. Android系統啟動
init.rc啟動(系統啟動的配置文件)
- servicemanager(binder守護線程)
- Runtime
- Zygote
[app_main.cpp](https://www.androidos.net.cn/android/2.3.7_r1/xref/frameworks/base/cmds/app_process/app_main.cpp)------->/frameworks/ base/ cmds/ app_process/ app_main.cpp
- Start VM
- System Server
- Start Android Services
Register to ServiceManager
實際真正起作用的是[AndroidRuntime.cpp](https://www.androidos.net.cn/android/2.3.7_r1/xref/frameworks/base/core/jni/AndroidRuntime.cpp)(\frameworks\base\core\jni\AndroidRuntime.cpp)
- Start Launcher
init.rc的源碼在根目錄: /system /core/ rootdir/ init.rc,可以參考網上的源碼[init.rc](https://www.androidos.net.cn/android/2.3.7_r1/xref/system/core/rootdir/init.rc)
3. 應用程序啟動
Running PackageManager
整體流程圖如下圖2所示
[點擊查看大圖](https://box.kancloud.cn/40971b42480183b0ff957cb05041200e_1943x1712.png)
:-: 
圖4 Android系統啟動流程
接下來就是應用程序的啟動過程了,可以參考老羅的系統源代碼情景分析,也可以參考[老羅的博客老羅Android之旅之應用程序的完整顯示過程](http://www.hmoore.net/alex_wsc/androids/477738)。也可以參考下圖APP的啟動流程
:-: 
圖5 APP啟動流程
>[warning] **注意**:上面這張圖只是一個大致流程,具體的細節可能有所出入。
關于Zygote和System進程的啟動過程的其他文章,同樣可參考老羅的系統源代碼情景分析,和他的博客文章——[Android系統進程Zygote啟動過程的源代碼分析](http://blog.csdn.net/luoshengyang/article/details/6768304)
在Android 系統中,存在如下3個十分重要的進程系統。
* Zygote 進程:被稱為“孵化”進程或“孕育”進程,功能和Linux系統的fork類似,用于“孕育”產生出不同的子進程。
* System 進程:是系統進程,是整個Android Framework 所在的進程,用于啟動Android系統。其核心進程是system_server,它的父進程就是Zygote
* 應用程序進程:每個Android應用程序運行后都會擁有自己的進程,這和Windows 資源管理器中的體現的進程是同一個含義。
>[info] **注意**:Dalvik 虛擬機的實現離不開進程管理,其進程管理特別依賴于Linux 的進程體系。例如要為應用程序創建一個進程, 會使用Linux 的FORK機制復制一個進程,因為復制進程的過程比創建進程的效率要高。并且在Linux 中進程之間的通信方式有很多,例如通道、信號、報文和共享內存等,這樣對進程管理將更加方便。
關于Zygote進程,還需要了解以下幾點
1. 系統啟動時init進程會創建Zygote進程,Zygote進程負責后續Android 應用程序框架層的其他進程的創建和啟動工作。
2. Zygote進程會首先創建一個SystemServer進程,SystemServer 進程負責啟動系統的關鍵服務,如包管理服務PackageManagerService和應用程序組件管理服務ActivityManagerService。
3. 當我們需要啟動一個Android應用程序時,ActivityManagerService會通過Socket進程間通信機制,通知Zygote進程為這個應用程序創建一個新的進程。
當Zygote進程在使用Linux的fork機制時有如下三種不同的方式。
* fork():孕育一個普通的進程,該進程屬于Zygote進程。
* forkAndSpcecialize():孕育一個特殊的進程,該進程不再是Zygote進程。
* forkSystemServer():孕育一個系統服務進程。
:-: 
圖5 fork進程的關系
Zygote進程可以再孕育出其他進程,非Zygote進程則不能孕育出其他進程。當終止系統服務進程后, 也必須終止其父進程。
Zygote 本身是一個應用層的程序,和驅動、內核模塊沒有任何關系。Zygote的啟動由Linux的init啟動。啟動后看到的進程名叫zygote,其最初的名字是app_process,通過直接調用pctrl把名字給改成了“zygote ” 。
從總體架構上看,Zygote是一個簡單的典型C/S結構。其他進程作為一個客服端向Zygote發出“孕育”請求,當Zygote接收到命令后就“孕育”出一個Activity進程。
#### **Dalvik虛擬機運行相關**
**創建一個虛擬機**
:-: 
圖 6 創建運行Dalvik虛擬機
* **使用工具**
- dalvikvm
當Java 程序運行時,都是由一個虛擬機來解釋Java 的字節碼,將這些字節碼翻譯成本地CPU 的指令碼,然后再執行。對Java 程序而言,負責解釋并執行的就是一個虛擬機,而對于Linux 而言,這個進程只是一個普通的進程,它與一個只有一行代碼的Hello World 可執行程序無本質的區別。所以啟動一個虛擬機的方法就跟啟動任何一個可執行程序的方法是相同的,那就是在命令行下輸入可執行程序的名稱,并在參數中指定要執行的Java 類。dalvikvm 的作用就是創建一個虛擬機并執行參數中指定的Java 類。
- dvz
在Dalvik 虛擬機中, dvz 的作用是從Zygote進程中孵化出一個新的進程,新的進程也是一個Dalvik虛擬機。該進程與dalvikvm 啟動的虛擬機的區別在于該進程中已經預裝了Framework的大部分類和資源。
* app_process
dalvikvm 和dvz 是通用的兩個工具, 然而Framework在啟動時需要加載并運行如下兩個特定Java類:ZygoteInit.java和SystemServer.java。
為了便于使用,系統才提供了一個app_process進程,該進程會自動運行這兩個類,從這個角度來講, app_process 的本質就是使用dalvikvm 啟動ZygoteInit.java。并在啟動后加載Framework中的大部分類和資源。
如何創建虛擬機并執行指定的class文件的。其源代碼在文件frameworks/base/cmds/app_ main.cpp 中,該文件中的關鍵代碼有如下兩處:
第一處:先創建一個App Runtime 對象;
第二處:調用runtime 的start()方法啟動指定的class 。
在系統中只有一處使用了app_process ,那就是在init.rc 中。因為在使用時參數包含了“ -zygote ” 及“ -start-system-server ",所以這里僅分析包含這兩個參數的情況。start()方式是類AppRuntime 的成員函數,而AppRuntime 是在該文件中定義的-個應用類,其父類是AndroidRuntime,該類的實現在文件frameworkds/base/core/jni/AndroidRuntime.cpp 中。在函數start()中,首先調用startVm()創建了一個vm 對象,然后就和dalvikvm一樣先找到Class(), 再執行class 中函數main(),使用startVm() 函數創建vm對象。
由上述過程可以看出,app_process和dalvikvm 在本質上是相同的,唯一的區別就是app_process可以指定一些特別的參數,這些參數有利于Framework啟動特定的類,并進行一些特別的系統
環境參數設置。
**Dalvik虛擬機的初始化:**
1. 開始虛擬機的準備工作
2. 初始化跟蹤顯示系統
3. 初始化垃圾回收器
4. 初始化線程列表和主線程環境參數
5. 分配內部操作方法的表格內存
6. 初始化虛擬機的指令碼相關的內容
7. 分配指令寄存器狀態的內存
8. 分配指令寄存器狀態的內存
9. 初始化虛擬機最基本用的Java 庫
10. 進一步使用的Java 類庫線程類
11. 初始化虛擬機使用的異常Java 類庫
12. 釋放字符串晗希表
13. 初始化本地方法庫的表
14. 初始化內部本地方法
15. 初始化JNI 調用表
16. 緩存Java 類庫里的反射類
#### **進程間通信**
對于IPC(Inter-Process Communication, 進程間通信),**Linux現有管道、消息隊列、共享內存、套接字、信號量、信號**這些IPC機制,Android額外還有Binder IPC機制,Android OS中的**Zygote進程的IPC采用的是Socket機制**,在**上層System Server、Media Server以及上層App之間更多的是采用Binder IPC方式來完成跨進程間的通信**。對于Android上層架構中,很多時候是在同一個進程的線程之間需要相互通信,例如**同一個進程的主線程與工作線程之間的通信,往往采用的Handler消息機制。**
* **Binder IPC原理**
Binder通信**采用C/S架構**,從組件視角來說,包含Client、Server、ServiceManager以及binder驅動,其中ServiceManager用于管理系統中的各種服務。
:-: 
圖7 startService過程所涉及的Binder對象的架構圖
* **Socket**
**Socket通信方式也是C/S架構**,比Binder簡單很多。在Android系統中采用Socket通信方式的主要:
* zygote:用于孵化進程,系統進程system_server孵化進程時便通過socket向zygote進程發起請求;
* installd:用于安裝App的守護進程,上層PackageManagerService很多實現最終都是交給它來完成;
* lmkd:lowmemorykiller的守護進程,Java層的LowMemoryKiller最終都是由lmkd來完成;
* adbd:這個也不用說,用于服務adb;
* logcatd:這個不用說,用于服務logcat;
* vold:即volume Daemon,是存儲類的守護進程,用于負責如USB、Sdcard等存儲設備的事件處理。
等等還有很多,這里不一一列舉,**Socket方式更多的用于Android framework層與native層之間的通信**
* **Handler**
**Binder/Socket用于進程間通信,而Handler消息機制用于同進程的線程間通信**,Handler消息機制是由一組MessageQueue、Message、Looper、Handler共同組成的,為了方便且稱之為Handler消息機制。
有人可能會疑惑,**為何Binder/Socket用于進程間通信,能否用于線程間通信呢?答案是肯定,對于兩個具有獨立地址空間的進程通信都可以,當然也能用于共享內存空間的兩個線程間通信,這就好比殺雞用牛刀**。接著可能還有人會疑惑,那**handler消息機制能否用于進程間通信?答案是不能,Handler只能用于共享內存地址空間的兩個線程間通信,即同進程的兩個線程間通信**。很多時候,Handler是工作線程向UI主線程發送消息,即App應用中只有主線程能更新UI,其他工作線程往往是完成相應工作后,通過Handler告知主線程需要做出相應地UI更新操作,**Handler分發相應的消息給UI主線程去完成。這只是Handler消息機制的一種處理流程,是不是只能工作線程向UI主線程發消息呢?其實不然,可以是UI線程向工作線程發送消息,也可以是多個工作線程之間通過handler發送消息。高煥堂老師說過,主線程內部也可以通過handler來傳遞消息**
**主線程丟信息給自己**
如下面的代碼----->主線程丟信息給自己
~~~
// ac01.java
//……..
public class ac01 extends Activity implements OnClickListener {
private Handler h;
public void onCreate(Bundle icicle) {
//……..
h = new Handler(){
public void handleMessage(Message msg) {
setTitle((String)msg.obj);
}}; }
public void onClick(View v) {
switch (v.getId()) {
case 101: h.removeMessages(0);
Message m = h.obtainMessage(1, 1, 1, "this is my message.");
h.sendMessage(m); // 將Message送入MQ里
break;
case 102: finish();
break;
}
}
}
~~~
#### 下面是**高煥堂老師的程序員到架構師課程關于進程的知識摘要**
**IPC通信概念**
* IPC(Inter-Process Communication)通信,是跨越兩個不同進程(Process)之通信。
* 一般而言,一個Android應用程序里的各組件(如Activity、Service等)都在同一個進程里執行。這種在同一進程內的通信,又稱為**短程通信**,意味著,兩個Activity在同一個進程(Process)里執行。
* 相對地,**遠程(Remote)通信**的意思是:兩個組件(如Activity或Service)分別在不同的進程里執行;兩者之間是IPC通信,又稱遠程通信。
**IPC通信的效率**
* 當我們**啟動某一支應用程序(App)時,Android系統里的Zygote服務孵化(Fork)一個新進程(Process)給它,然后將它(該App)加載到這個新誕生的進程里**。
* 基于Linux的安全限制,以及進程的基本特性(例如,不同進程的地址空間是獨立的),如果兩個類(或其對象)在同一個進程里執行時,兩者溝通方便也快速 。但是,當它們分別在不同的進程里執行時,兩者溝通就屬于IPC跨進程溝通了,不如前者方便,也慢些 。
**Android的進程概念**
* 一個進程是一個獨立的執行空間,不會被正在其它進程里的程序所侵犯。這種保護方法是Android的重要安全機制。于是,得先認識進程的內涵,才能進一步了解跨進程IPC機制。
* 在**Android的進程里,有一個虛擬機(Virtual Machine,簡稱VM)的對象,可執行Java代碼,也引導JNI本地程序的執行,實現Java與C/C++之間的溝通**;如下圖:
**每一進程有:一個VM對象、主線程、MQ和Looper**
:-: 
圖8 Android進程概念
* **每一個進程在誕生時,都會誕生一個主線程(Main Thread),以及誕生一個Looper類的對象和一個MQ(Message Queue)數據結構**。每當主線程作完事情,就會去執行Looper類。此時,不斷地觀察MQ的動態。如下圖:
**不同進程的地址空間是獨立的**
:-: 
圖9 獨立的進程空間
* 主線程最主要的工作就是處理UI畫面的事件(Event),每當UI事件發生時,Android框架會丟信息(Message)到MQ里。主線程看到MQ有新的信息時,就取出信息,然后依據信息內容而去執行特定的函數。執行完畢,就再繼續執行Looper類,不斷地觀察MQ的動態。
* 剛才說明了,當兩個類都在同一個進程里執行時,兩者之間的溝通,只要采取一般的函數調用(Function Call)就行了,既快速又方便。一旦兩個類分別在不同的進程里執行時,兩者之間的溝通,就不能采取一般的函數調用途徑了,只好采取IPC溝通途徑。
**IPC的IBinder接口 -- 定義與實現**
Android框架的IPC溝通依賴單一的IBinder接口。此時Client端調用IBinder接口的transact()函數,透過IPC機制而調用到遠方(Remote)的onTransact()函數。
在Android的源代碼里,Java層的IBinder接口是定義于IBinder.java代碼文檔里。此程序文件如下:
/frameworks/base/core/java/android/os/IBinder.java
~~~
public interface IBinder {
.......................
public String getInterfaceDescriptor() throws RemoteException;
public boolean pingBinder();
public boolean isBinderAlive();
public IInterface queryLocalInterface(String descriptor);
public void dump(FileDescriptor fd, String[] args) throws RemoteException;
public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException;
public boolean transact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException;
public interface DeathRecipient {
public void binderDied();
}
public void linkToDeath(DeathRecipient recipient, int flags)
throws RemoteException;
public boolean unlinkToDeath(DeathRecipient recipient, int flags);
}
~~~
IBinder接口定義了一些函數,可以讓Client程序可以進行跨進程的調用(當然也能支持同進程的短程調用)。其中,最主要的一個函數就是:transact()函數。
**IBinder接口的實現類**
在Android的框架里,也撰寫了Binder基類和BinderProxy類別來實作 IBinder接口。
Binder基類的很重要目的是支持跨進程調用Service,也就是讓遠程的Client可以跨進程調用某個Service。
Binder基類的主要函數是:
* transact()函數
用來實作IBinder的transact()函數接口。
* execTransact()函數
其角色與transact()函數是相同的,只是這是用來讓C/C++本地程序來調用的。
* onTransact()函數
這是一個抽象函數,讓應用子類來覆寫(Override)的。上述的transact()和execTransact()兩者都是調用onTransact()函數來實現反向調用(IoC, Inversion of Control)的。
* init()函數
這是一個本地(Native)函數,讓JNI模塊來實現這個函數。Binder()構造函數(Constructor)會調用這個init()本地函數。
**Java層的BinderProxy基類定義**
* 這個BinderProxy類也定義在Binder.java檔案里
* 當我們看到類別名稱是 XXXProxy時,就自然會聯想到它是擺在Client進程里,擔任Service端的分身(Proxy)。
* 由于跨進程溝通時,并不是從Java層直接溝通的,而是透過底層的Binder Driver驅動來溝通的,所以Client端的Java類別(如Activity)必須透過BinderProxy分身的IBinder接口,轉而調用JNI本地模塊來銜接到底層Binder Driver驅動服務,進而調用到正在另一個進程里執行的Service。
* 當Client透過IBinder接口而調用到BinderProxy的transact()函數,就調用到其 JNI本地模塊的transact()函數,就能進而銜接到底層Binder Driver驅動服務了。
:-: 
圖10 binder通信模型
在上圖里,從JNI本地模塊拉了一條紅色虛線,表示這并非直接的通信途徑。也就是,實際上是透過底層Binder Driver驅動才調用到BBinder的IBinder接口。
- 前言
- Android系統的體系結構
- Dalvik VM 和 JVM 的比較
- Android 打包應用程序并安裝的過程
- Android ADB工具
- Android應用開發
- Android UI相關知識總結
- Android 中window 、view、 Activity的關系
- Android應用界面
- Android中的drawable和bitmap
- AndroidUI組件adapterView及其子類和Adapter的關系
- Android四大組件
- Android 數據存儲
- SharedPreference
- Android應用的資源
- 數組資源
- 使用Drawable資源
- Material Design
- Android 進程和線程
- 進程
- 線程
- Android Application類的介紹
- 意圖(Intent)
- Intent 和 Intent 過濾器(Google官網介紹)
- Android中關于任務棧的總結
- 任務和返回棧(官網譯文)
- 總結
- Android應用安全現狀與解決方案
- Android 安全開發
- HTTPS
- 安卓 代碼混淆與打包
- 動態注入技術(hook技術)
- 一、什么是hook技術
- 二、常用的Hook 工具
- Xposed源碼剖析——概述
- Xposed源碼剖析——app_process作用詳解
- Xposed源碼剖析——Xposed初始化
- Xposed源碼剖析——hook具體實現
- 無需Root也能Hook?——Depoxsed框架演示
- 三、HookAndroid應用
- 四、Hook原生應用程序
- 五、Hook 檢測/修復
- Android 應用的逆向與加固保護技術
- OpenCV在Android中的開發
- Android高級開發進階
- 高級UI
- UI繪制流程及原理
- Android新布局ConstraintLayout約束布局
- 關鍵幀動畫
- 幀動畫共享元素變換
- Android異步消息處理機制完全解析,帶你從源碼的角度徹底理解
- Android中為什么主線程不會因為Looper.loop()里的死循環卡死?
- 為什么 Android 要采用 Binder 作為 IPC 機制?
- JVM 中一個線程的 Java 棧和寄存器中分別放的是什么?
- Android源碼的Binder權限是如何控制?
- 如何詳解 Activity 的生命周期?
- 為什么Android的Handler采用管道而不使用Binder?
- ThreadLocal,你真的懂了嗎?
- Android屏幕刷新機制