1. 程式人生 > 其它 >鵝廠資深Android開發帶你瞭解面試重點Framework,掌握更加核心的技術

鵝廠資深Android開發帶你瞭解面試重點Framework,掌握更加核心的技術

前言

今天,想跟大家聊聊,Framework開發的那些事。

系統應用開發,現在來說,已經開始脫離系統,單獨拿出來開發,系統定製介面,已提供給應用呼叫,用來增強功能。

原生的桌面,撥號,設定,已經沒法做出差異化優勢,因此都費盡心機,來進行應用深度開發。

對於之前維護系統應用模組的人來講,修修補補,真的沒有什麼成長。每天的工作來說,沒有很深的技術壁壘,很容易被別人攻陷。

比如設定,比如聯絡人,在小的改動,修改故障的時候,沒有非常高的要求,做過應用開發的,都可以過來參合一腳,改改問題。而讓一個應用開發得去修改系統介面,估計改的心累,並且猶豫不決。

技術壁壘,也便是自己的競爭優勢。只有頑強的技術能力,並持之以恆的學習,擴充自己的深度,廣度,那麼你的位置則牢不可破,不會輕易被替代。

Framework的核心技術

今天從自身的角度,講講系統應用開發,該如何向Framework進軍,進行學習,掌握更加核心的技術。

有人會說,我做應用風生水起,也遊刃有餘,不比你們做系統Framework的差,何必把系統應用開發的貶的一文不值。這裡要說一下,文中沒有這個意思,你的應用做的有聲有色,賺的盆滿缽滿,這裡肯定有其因素。比如它的效能,它的介面絢麗,百變主題。或者它有智慧識別,等等。這些都叫做差異化產品,有其亮點,特色,才能殺出重圍。

而系統應用開發,我這裡偏向於手機整機開發中的OEM廠商,主要做出系統,能夠保證功能正常,不會花費大量人力精力去做應用深度開發,系統重構的。這裡主要會以追求速度,同時滿足客戶的硬體要求,比如多個霍爾器件,多個溫度感測器,多個皮套功能,等等,但很少去大量改動應用架構,以免影響最終量產。

以上,就是特指的這個應用開發人員。隨後,我來講講,Framework需要掌握哪些知識呢?

作業系統

熟悉我的人都知道,我特喜歡把這個放在第一位,原因很簡單,它確實支撐了我隨後的所有知識根基,讓我能夠從容不迫的,將一個個系統拆解出來。

我們就拿安卓來講,啟動過程

Android 啟動過程框架

跟linux如出一轍,所以很容易遷移過來,同時,差異化的init程序,完成初始任務,建立安卓世界的孵化器,既然這裡要進入安卓世界,而安卓世界的基礎語言是java,那麼就需要一個Java虛擬機器,於是孵化器就要構造一個虛擬機器,用來解析執行Java編譯出來的位元組流。而孵化器本身是由c cpp語言實現,於是Java虛擬機器就是由c cpp語言寫出來的,linux作業系統也是c(還有一些彙編)寫出來的,於是Java虛擬機器執行的Java語言,就需要跟c cpp打交道,於是就有了JNI。

孵化器做了幾件事情:

  1. 完成Java虛擬機器的構造

  2. 完成JNI對接Java與c的橋樑

  3. 載入公共的共享庫

  4. 等待別人給它發訊息,建立新程序

在這期間,孵化器要做一件事情,便是建立system_server ,這個程序要做什麼呢?我們建立了一個可以執行Java的虛擬機器,這時我們就要提供一堆系統介面,用來協助應用開發,比如請求網路啦,比如建立介面啦,比如定位啦,獲取儲存卡啦,等等支援,方便使用者開發功能。一個平臺的好壞,往往取決於它的功能是否強大,是否有豐富的技術文件,以及開發除錯工具。

所以就有了一堆執行緒,比如AMS,WMS,PMS,BT,WIFI,這些都可以在/proc/{ system_server_pid}/ tast找到記錄。

有了這些執行緒,那麼我們就可以輕鬆的去實現很多功能啦。這時我們就要配套的開發工具,比如AS編輯器,可以編輯,編譯出來APK,安裝到手機執行。

關於作業系統,需要掌握的知識點為:

  1. 程序,執行緒概念

  2. 互斥,死鎖機制與原理,如何避免死鎖

  3. 記憶體管理機制,虛擬記憶體

  4. 靜態庫與動態庫的區別

  5. 程序之間的記憶體屏障,如何通訊(IPC)

  6. binder的通訊優勢

這裡先想到這些,注意不是要完成懂所有機制,要的是整體理解即可。如下問題,請思考下,看是否能夠答上來。

如果我寫了一個應用,名字叫做,com.codegg.home 在主activity裡面,載入一個佈局,layout_main. xml,佈局裡面寫入了一個TextView,那麼我想除錯這個TextView,要在com.codegg.home這個程序下斷點,還是在system_server程序下斷點呢?如果是想除錯ActivityThread. java的話?應該在哪個程序下斷點呢?

以上答案,都是com.codegg.home下斷點,原因是這兩個當前的執行程序,都是在com.codegg.home裡,所以要除錯的話,要在com.codegg.home程序下斷點。

那麼我們再來思考下,我現在要去追應用的啟動過程,start Activity的流程,要在哪個地方下斷點呢?

我們知道這個流程,最終核心的都在Activity manager server裡面,而它是在system server程序裡面,以一個執行緒的狀態存在,於是我們要除錯,就要在system server上面下斷點了。

搞清楚了system server後,以我們熟悉的AMS WMS PMS 舉例。這些服務執行緒,完成應用的請求任務,將結果返回給應用。比如檢視當前執行的所有Activity,就是應用發起請求,從作業系統那裡,先找到server manager,這個手裡拿到一堆服務的控制代碼,也可以說令牌,你只能通過這個找到它。

當server manager一看你有許可權,就幫你把對應的AMS的控制代碼給你,這個控制代碼作業系統也認識,對應到system server的AMS引用上,也就是你通過這個控制代碼,呼叫它的方法,作業系統就會將你的請求,傳遞到system server中去,同時作業系統知道這個控制代碼是AMS的第20號(這個20號代表查詢當前執行的所有Activity的方法),然後就喚醒system server,同時從binder執行緒池,這個執行緒跟AMS一樣,是個執行緒,從執行緒池拿出一個,呼叫AMS的20號方法。

呼叫完成後,從作業系統層面,把資料交給呼叫的應用,實現資料傳輸。這裡面定義的傳遞資料格式是包裹,也就是序列化資料。

瞭解程序通訊

好了,這塊就說這麼多,主要是說下程序通訊,以及binder這種通訊的簡單邏輯。這裡說下,為什麼要通訊。

因為作業系統設計,管理的軟體單元是程序,程序間本身不聯絡,彼此看不見。一個程序想跟另一個說話,他兩都認識的人是作業系統。因為他們是由作業系統管理的。作業系統通過從硬碟將程式裝載進入記憶體,同時給每一個分配了程序號,於是他們就都在系統裡面有了標記,同時每個都起了名字,一個叫我就喜歡吃,一個叫我就喜歡喝。喜歡喝的一個人孤單,他不認識喜歡吃的,他就問作業系統,有沒有人喜歡吃的,作業系統一查,說有啊,然後把喜歡吃的的程序號給他,他就可以找到喜歡吃的了。

然後作業系統給他了一輛車,讓他把想給喜歡吃的的東西,裝在車上寄過去。這個車子是作業系統提供的,這個車子就是通訊方式。比如汽車,飛機,步行。

於是程序間的通訊方式就是,從作業系統找到目標,然後拿到通訊方式,用作業系統給的通訊工具,進行通訊。

資料結構和演算法

這塊完成了,我們再來講一個內容:

檔案=檔案頭+檔案內容

我們發現,這裡MP3格式,OGG格式,都屬於一個檔案的格式宣告,這個我們可以用HEX工具開啟MP3檔案,可以看到剛開始的位置,這塊屬於描述後面的內容該如何解析,比如檔名字,檔案大小,檔案格式,系統根據這個描述,嘗試用對應的解碼器解碼,解碼完成後進行播放。

這裡解碼器如何解碼,就是演算法。而檔案頭,就是描述這個檔案的資料結構。

於是,我們就知道

程式=資料結構+演算法

比如我要寫個貪吃蛇,如何描述蛇的狀態,長度,當前軌跡,這些都是需要表徵出來,然後圍繞著這個描述內容,進行操作,這塊就屬於演算法。

完成的程式,執行起來,就是程序。所以程序是一個存在於記憶體的東西,作業系統用一個表格記錄程序資料,比如程序號,父類程序,程序開啟的檔案控制代碼,程序當前狀態,程序的上下文(上下文是儲存當前CPU的暫存器,儲存現場用的,因為暫存器是隻有一份,當一個程序被打斷時候,另個程序執行,那麼之前的就要把它當前的暫存器存下來,防止被別人蓋掉,等到下次自己執行的時候,再恢復回來,保證自己執行正常),程式是存在硬碟或者其他儲存裝置,掉電不會丟失,而程序是記憶體的,所以掉電就不再了。

程式如何載入,系統如何識別的呢?這就又回到開頭的地方,資料結構加演算法,也叫檔案頭和檔案內容。原始碼經過編譯連結,變成一個檔案,我們親切的叫它可執行檔案。那麼我們來說說它。

我們常見的兩種可執行檔案,windows上面稱為PE格式,linux稱為ELF,兩者都是從COFF格式演化來的,這塊參考《連結器與載入器》,喜歡感興趣,可以下載閱讀此書。

程式是如何在CPU執行的?

那麼有了格式描述,作業系統就知道如何解析它了,然後把對應的程式碼段,資料段,堆疊區域配置好,將程式碼裝載進入記憶體中,然後將下一條執行位置,也就是PC暫存器,指向這個可執行檔案配置的text 入口,這個就是程式的入口點,這個我們去寫的main方法,可以簡單理解成入口,實際情況是在這個前面,系統加入了一些程式碼,為執行此程式做準備,準備OK才會真正呼叫到main方法,這段程式碼叫建立此程序的環境,比如引數,堆疊初始化。

聊到這裡,我們從別的緯度,再來看看。

數位電路的與或非邏輯電路,開啟了新世界的大門。我們用斷點,通電,表示兩個狀態。我們不能說,好像有電,好像沒電,所以,計算機的世界,定義了二進位制,因為是非可以界定,孰是孰非不好界定。

於是,在我們的電路板上,規定了0-0.6V,代表了沒電,4.4-5V,代表了有電,中間的數值,代表了器件的錯誤,不穩定性。

於是沒電用0表示,有電用1表示,實際世界就是兩個區間電壓。

CPU在石英晶振的推動下,執行一條條指令。指令是什麼呢?就是一串串數字,每一串代表一個具體含義。

所以,CPU能夠執行多少條指令,是考量它是否強大的一個重要引數,另一個是它執行一天指令的時間,也叫指令週期,越短越好。也就是兩個CPU同時做一個加法,誰用時短誰就強。

CPU拿到一條指令,就會在石英晶振的推動下,將這條指令執行完,然後將PC暫存器加1,讀取下一條指令。

我們經常遇到的非法指令,就是因為CPU拿到了一個不認識的資料串,導致異常。比如它的指令集裡面,有加法,有減法,你給他說你給我翻個跟頭(非法指令),他罵了一句去你的吧,老子不會(異常報錯)。一般這種情況是指令不識別,比如你用了新的arm指令,又在舊的arm板子執行這個程式,就會掛掉,提示非法指令。

剛開始的作業系統,嵌入式的作業系統,是沒有做記憶體保護,就是程式段可以跳到資料段執行,當然現在加入了記憶體管理單元,會將資料段記憶體描述成可讀可寫不可執行,如果PC(程式暫存器)指向了這個地方,去讀取執行的時候,就會報非法訪問。

如果沒有保護,你去讀取資料段的資料,作為指令執行,出現指令異常就太正常了。

好了,今天就給大家介紹這麼多。

最後

BATJ 大牛筆記《Android Framework 精編核心解析》

第一節 Binder 系列—開篇
第二節 Binder Driver 初探
第三節 Binder Driver 再探
第四節 Binder 啟動 ServiceManager
第五節獲取 ServiceManager
第六節註冊服務(addService)
第七節獲取服務(getService)
第八節 framework 層分析
第九節如何使用 Binder
第十節如何使用 AIDL
第十一節 Binder 總結
第十二節 Binder 面試題全解析
........

Android開發還需要具備哪些技能?

對於程式設計師來說,要學習的知識內容、技術有太多太多,要想不被環境淘汰就只有不斷提升自己,從來都是我們去適應環境,而不是環境來適應我們!

但其實客戶端開發的知識點就那麼多,面試問來問去還是那麼點東西。所以面試沒有其他的訣竅,只看你對這些知識點準備的充分程度。so,如果出去面試先看看自己複習到了哪個階段就好。

複習路線:
《移動架構師V6.0移動開發架構師70W年薪成長路線》

最後我在這裡分享一份《Android大廠高頻面試題解析大全》,裡面內容很多也很系統,包含了很多內容:Android 基礎、Java 基礎、Android 原始碼相關分析、常見的一些原理性問題等等,可以很好地幫助我們深刻理解Android相關知識點的原理以及面試相關知識

這份資料把大廠面試中常被問到的技術點整理成了 PDF ,包知識脈絡 + 諸多細節;還有 高階架構技術進階腦圖 幫助大家學習提升進階,也節省大家在網上搜索資料的時間來學習,也可以分享給身邊好友一起學習。

需要《Android Framework 精編核心解析》、《Android大廠高頻面試題解析大全》以及《移動架構師V6.0移動開發架構師70W年薪成長路線》的朋友可以點選這裡免費獲取。