Android開機流程linux
當按開機鍵的時候,引導芯片開始從固化在ROM的預設代碼開始執行,而後加載引導程序到RAM
BootLoader,又稱爲引導程序。它是在操做系統運行以前運行的一段程序
BootLoader負責初始化軟件運行所須要的最小硬件環境,最後加載內核到內存android
這個入口的函數是start_kernel函數
start_kernel函數執行到最後調用了reset_init函數進行後續的初始化
start_kernel最終啓動用戶空間的init程序windows
當初始化內核以後,init進程負責解析init.rc配置文件, 就會啓動一個至關重要的祖先進程,也就是init進程,在Linux中全部的進程都是由init進程直接或間接fork出來的架構
* /system/bin/app_process_Zygote服務啓動的進程名 * --start-system-server 代表Zygote啓動完成後,須要啓動System_Server進程 * socket zygote stream 666在Zygote啓動時,建立一個權限爲666的socket。此socket用來請求zygote建立新進程 * socket的fd保存在名稱爲"ANDROID_SOCKET_zygote"的環境變量中
init進程負責建立系統中最關鍵的幾個核心daemon(守護)進程,尤爲是zygote和System_Server進程app
1. zygote進程 android啓動的第一個Dalvik 虛擬機,它將負責啓動Java世界的進程 2. zygote虛擬機啓動子進程system_server,同時也能夠看出zygote中定義了一個Socket,綁定666端口,用於接收ActivityManagerService啓動應用程序的請求 3. System_Server進程 Binder通訊的基礎,它還提供了property service(屬性服務),相似於windows系統的註冊表服務 4. 系統裏面重要的服務都是在這個進程裏面開啓的,例如AMS, WindowsManager, PackageManagerService等等都是由這個System_Server fork出來的 5. 在System_Server進程開啓的時候,就會初始化ActivityManagerService 。同時,會加載本地系統的服務庫,調用createSystemContext()建立系統上下文,建立ActivityThread及開啓各類服務等等 6. system_server中開啓了核心系統服務,並將系統服務添加到ServiceManager中,而後系統進入SystemReady狀態
啓動Home Activitysocket
概況 1. 系統加電,執行bootloader。Bootloader負責初始化軟件運行的最小硬件環境,最後加載內核到內存 2. 內核加載到內存後,進入內核引導階段,在內核引導的最後,調用start_kernel進入內核啓動階段。start_kernel最終啓動用戶空間的init程序 3. init負責解析init.rc配置文件,開啓系統守護進程。2個最重要的守護進程是zygote進程和serverManager進程。zygote是android啓動的第一個Dalvik虛擬機,ServiceManager服務是Binder通訊的基礎 4. zygote虛擬機啓動子進程system_server,在system_server中啓動了核心系統服務,並將系統服務添加到ServiceManager中,而後系統進入SystemReady狀態 5. 在SystemReady狀態,ActivityManagerService與zygote中的socket通訊,經過zygote啓動home應用,進入系統界面 * 從步驟3開始, init啓動後,上層的實現 1. init啓動的核心Daemon服務包括Android的第一個Dalvik虛擬機Zygote 2. zygote定義一個socket,用於接受ActivityManangerService啓動應用的請求 3. zygote經過fork系統調用建立system_server進程 4. 在system_server進程中,將會啓動系統核心服務以及其餘服務 5. 系統服務啓動後會註冊到ServiceManager中,用於Binder通訊 6. ActivityManagerService進入systemReady狀態 7. 在systemReady狀態,ActivityManangerService會與zygote的Socket通訊,請求啓動Home 8. zygote收到AMS的鏈接請求後,執行runSelectLoopMode處理請求 9. zygote處理請求會經過forkAndSpecialize啓動新的應用進程,並最終啓動Home
Message - Message表明一個行爲what或者一串動做Runnable, 每個消息在加入消息隊列時,都有明確的目標Handler ThreadLocal - 線程本地存儲區(Thread Local Storage,簡稱爲TLS),每一個線程都有本身的私有的本地存儲區域,不一樣線程之間彼此不能訪問對方的TLS區域。ThreadLocal的做用是提供線程內的局部變量TLS,這種變量在線程的生命週期內起做用,每個線程有他本身所屬的值(線程隔離) MessageQueue (C層與Java層都有實現) - 以隊列的形式對外提供插入和刪除的工做, 其內部結構是以雙向鏈表的形式存儲消息的 Looper (C層與Java層都有實現) - Looper是循環的意思,它負責從消息隊列中循環的取出消息而後把消息交給Handler處理 Handler - 消息的真正處理者, 具有獲取消息、發送消息、處理消息、移除消息等功能
普通的線程是沒有looper的,若是須要looper對象,那麼必需要先調用Looper.prepare方法,並且一個線程只能有一個looper
Handler是如何完成跨線程通訊的ide
* Android中採用的是Linux中的管道通訊 * 關於管道,簡單來講,管道就是一個文件 * 在管道的兩端,分別是兩個打開文件文件描述符,這兩個打開文件描述符都是對應同一個文件,其中一個是用來讀的,別一個是用來寫的 * 消息隊列建立時,會調用JNI函數,初始化NativeMessageQueue對象。NativeMessageQueue則會初始化Looper對象 * Looper的做用就是,當Java層的消息隊列中沒有消息時,就使Android應用程序主線程進入等待狀態,而當Java層的消息隊列中來了新的消息後,就喚醒Android應用程序的主線程來處理這個消息
整個消息機制流程函數
Handler經過sendMessage()發送Message到MessageQueue隊列 Looper經過loop(),不斷提取出達到觸發條件的Message,並將Message交給target來處理 通過dispatchMessage()後,交回給Handler的handleMessage()來進行相應地處理 將Message加入MessageQueue時,處往管道寫入字符,能夠會喚醒loop線程;若是MessageQueue中沒有Message,並處於Idle狀態,則會執行IdelHandler接口中的方法,每每用於作一些清理性地工做
Activity的window組成,Activity內部有個Window成員,它的實例爲PhoneWindow,PhoneWindow有個內部類是DecorView,這個DecorView就是存放佈局文件的,裏面有TitleActionBar和咱們setContentView傳入進去的layout佈局文件oop
+ measure, 遞歸測量view的大小。有3種測量模式 - MeasureSpec.EXACTLY表示肯定大小 - MeasureSpec.AT_MOST表示最大大小 - MeasureSpec.UNSPECIFIED不肯定 + layout,遞歸佈局view的位置 + draw,遞歸繪製view - ViewRootImpl中的代碼會建立一個Canvas對象,而後調用View的draw()方法來執行具體的繪製
進程空間分配源碼分析
Binder跨進程通訊(IPC)的原理
使用步驟:
註冊服務
* Server進程向Binder驅動發起服務註冊請求 * Binder驅動將註冊請求轉發給ServiceManager進程 * ServiceManager進程添加該服務 * 此時ServiceManager進程擁有該服務信息
獲取服務
* Client向Binder驅動發起獲取服務的請求,傳遞要獲取的服務名稱(service name) * Binder驅動將該請求轉發給ServiceManager進程 * ServiceManager查找到Client須要的Server對應的服務信息 * 經過Binder驅動將上述服務信息返回給Client進程 * 此時client進程與server進程已經創建了鏈接
使用服務
* Client進程將參數數據發到Server進程 1. client 進程將須要的傳送的數據放到client進程的共享內存;(當前線程被掛起) 2. Binder驅動從client的共享內存中讀取數據,並根據ServiceManager進程裏面的Server信息找到對應的Server進程 3. Binder驅動將數據copy到Server進程的共享內存裏,並通知Server進程解包 * Server進程根據Client進程要求,調用目標方法 1. 接到Binder驅動通知後,Server進程從線程池中取出線程,進行數據解包和調用目標方法 2. 將最終方法結果寫到本身的共享內存 * Server進程將目標方法的結果,返回給Client進程 1. Binder驅動程序將Server進程的共享內存裏面的數據(方法執行結果) copy 到client進程的共享內存 2. 通知client進程得到返回結果(此時client進程以前被掛起的線程被從新喚醒)
Client進程、Server進程 & Service Manager 進程之間的交互 都必須經過Binder驅動(使用 open 和 ioctl文件操做函數),而非直接交互
Client進程、Server進程 & Service Manager進程屬於進程空間的用戶空間,不可進行進程間交互
Binder驅動 屬於 進程空間的 內核空間,可進行進程間 & 進程內交互
Binder驅動 & Service Manager進程 屬於 Android基礎架構(即系統已經實現好了);而Client 進程 和 Server 進程 屬於Android應用層(須要開發者本身實現)
每一個Thread維護一個ThreadLocalMap映射表,這個映射表的key是ThreadLocal實例自己,value是真正須要存儲的Object
android自己就是linux系統 因此查看命令和linux同樣
dalvik.vm.heapstartsize 表示 初始內存大小是8m
dalvik.vm.heapgrowthlimit 表示標準內存大小是96m 通常應用都是這麼大
dalvik.vm.heapsize 表示 在manifest配置文件中application標籤下配置 android:largeHeap="true"時的內存大小
apk安裝包大小理論上沒有限制。可是各個應用商店爲了有大小限制google play 要求小於50M , 擴展包能夠擴展到2g
壓測: 800M的apk是沒問題的只是安裝的時間比較長。1.6G的apk包則把手機弄死機
ThreadPoolExecutor構造函數的maximumPoolSize決定
ART 的機制與 Dalvik 不一樣。在Dalvik下,應用每次運行的時候,字節碼都須要經過即時編譯器(just in time ,JIT)轉換爲機器碼,這會拖慢應用的運行效率,而在ART 環境中,應用在第一次安裝的時候,字節碼就會預先編譯成機器碼,使其成爲真正的本地應用。這個過程叫作預編譯(AOT,Ahead-Of-Time)。這樣的話,應用的啓動(首次)和執行都會變得更加快速。
即整個應用的主線程,只有這一個looper,無論有多少handler,最後都會回到這裏
public static void loop() { ... for (;;) { ... // This must be in a local variable, in case a UI event sets the logger Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); } msg.target.dispatchMessage(msg); if (logging != null) { logging.println("<<<<< Finished to " + msg.target + " " + msg.callback); } ... } }
設置Printer對象,判斷是否超過預期時間,notifyLog