1. 程式人生 > >專訪羅昇陽:老羅的Android之旅

專訪羅昇陽:老羅的Android之旅

「編者按」CSDN人氣博主羅昇陽將攜他的《Android系統原始碼情景分析》一書做客CSDN社群問答欄目擔任第九期的嘉賓,屆時會接受廣大網友的提問,歡迎各位網友前來與羅昇陽老師一起探討Android系統。他一直致力於從原始碼角度來研究Android系統,詮釋現代化移動作業系統的實現原理。以下為採訪正文:

羅昇陽(部落格),1984年出生,2007年畢業於浙江大學計算機系,取得學士學位,2010年畢業於上海交通大學計算機系,取得碩士學位。畢業後一直從事於網際網路軟體開發,並且致力於移動平臺的研究,特別是對Android平臺有深入的理解和研究。在國內知名IT技術社群CSDN上發表了一百多篇高質量的Android系統原創性文章,並且開設部落格專欄——《老羅的Android之旅》。積極與網友交流互動,深受大家喜愛,訪問量一直居於前茅。同時,著有《Android系統原始碼情景分析》一書。

CSDN:請和大家介紹下你和目前所從事的工作。

羅昇陽:我現在正在做一款和手遊相關的Android應用,玩家可以一邊玩遊戲一邊錄製以及直播。在中國,無論是傳統的PC網際網路,還是現在的移動網際網路,遊戲都是一個巨大的市場。在手遊超越頁遊追趕端遊的今天,手遊錄製和直播作為連線玩家和玩家、玩家和廠商之間的一個平臺,近年來在國內外都得到了追棒。在國外,今年5月初的時候,手遊錄製及分享社群Kamcord獲得了710萬美元的A輪融資;到5月中的時候,又傳來Google花10億美元收購遊戲直播公司Twitch的訊息。在國內,愛拍和ShareSDK也釋出了手遊錄製和分享相關的產品。

手遊錄製和直播產品吸引我的,除了它的巨大市場之外,還有它的技術含量。坦白說,在Android平臺上,至今還沒有一款使用者體驗好的手遊錄製應用。目前Android市場上的手遊錄製應用,不是效能問題,就是穩定性或者相容性問題。包括在iOS平臺上已經做得相當不錯的Kamcord,在Android平臺上也表現平平。究其原因有如下三點:

一是Android平臺沒有直接提供獲取遊戲畫面和聲音的介面。

二是Android平臺的差異化導致很難找到一個通用的技術方案使其在大部分手機上都能行之有效。在Root過的手機上,雖然可以使用截圖介面來獲取遊戲畫面,但是直接使用效率是很低的,難以滿足幀率要求。另外一個通過讀取Frame Buffer獲取遊戲畫面的方法,在到4.0之後,就更行不通了。

再者,由於是實時錄製,對視訊編碼的效能要求是很高的。使用軟編碼基本上是不可行的,必須要使用硬編碼。但是使用編碼又要考慮硬體上的適配,否則就很容易產生穩定性和相容性問題。

為了解決上述的技術難題,需要用到很底層的Android系統知識,例如Android系統的UI渲染機制和硬編碼等知識。要利用這些知識,沒有深厚的Android功底是很難辦得到的。由於我對Android系統有比較深的研究,因此我覺得去做這樣的一個產品是一個很有意思的挑戰。

當然,目前除了做手遊錄製和直播應用之外,還在研究做一些基於Android系統的穿戴式裝置,畢竟我的興趣點在於Android系統,而且穿戴式裝置也會是未來的方向之一。

CSDN:你是從什麼時候接觸到計算機的,是怎樣走上程式設計這條道路的?又是在何時開始接觸Android平臺並進行如此深入研究的呢?

羅昇陽:我接觸計算機的時間是比較晚的,上大學之前,除了在網咖,基本上就沒接觸過電腦了。大學選擇了計算機專業,才開始真正的接觸電腦。而且我很清楚地刻,大一開學大概一個月的時候,學校要進行計算機文化基礎上機考試,實際上就是考一下Word和Excel的操作。考試前有大概兩週時間讓你有空的時候去機房練習。對於一個以前沒怎麼接觸過計算機、打字都還不利索的孩子來說,果不其然就考掛了。後來補考了一次才及格。

由於學的是計算機專業,大一的時候就要開始程式設計的了。一開始學的就是C語言,不像現在很多人一開始學的是都是C#、Java、PHP這些高階又相當易用的語言了。後來才逐漸學習了C++、Java和C#等這些高階語言。剛開始學C語言還是很痛苦的,龍其學到指標、連結串列這些知識的時候。記得大一上學期的國慶節,還專門花了幾天的時候去啃了連結串列的實現原理。現在回想起來,一開始就選擇學習C語言是對的。因為無論你現在工作用的是什麼語言,如果想要把它背後依靠的平臺吃透,都不可避免地需要了解它的底層實現,而這些底層實現基本上都是離不開C/C++。或者換句話說,語言只是一個工具,要理解你的軟體實現原理,關鍵都是要理解軟體背後的計算機系統,而C是最接近計算機系統的語言。因此,我是非常建議有志於從事軟體開發的同學們,無論你現在、以後工作用的是什麼語言,都一定要學好C/C++。

接觸Android平臺是研究生畢業後工作的事了。正式接觸是2011年年初的時候,當時寫了一個簡單的五子棋遊戲。不過在2010年下半年的時候,就開始計劃要好好研究一下Android系統了。因為了解到Android系統是基於Linux核心實現的,所以2010年下半年的時候,主要就是去補Linux核心的基礎知識。其實激發我要去深入研究Android系統而不是單單是Android應用的動機,是當時在公司做的一款軟體的應用程式框架,是完全公司的一個團隊自行開發的,沒有采用在學校時接觸的MFC等通用框架。那時候對這套自行開發的應用程式框架很感興趣,但無奈我們只是業務團隊,平時只是使用這套框架,而沒有機會去深入研究。

2010年的時候,iOS已經很火了,Android也開始冒出尖尖頭了。由於Android背後的靠山的Google,而且它的原始碼是開放的,因此,就準備去研究一下Android系統的應用程式框架是怎麼實現的。這樣一來能跟上移動潮流,一來也能滿足自己的好奇心。從此就一發不可收拾,正式步入Android系統的世界了。

CSDN:你用兩年的時間煉就了深厚的Android內功修養,請問期間的學習之路是怎樣的?有什麼學習的心得和體會可分享?

羅昇陽:那兩年基本是把所有的業餘時間都花在了學習Android上,包括工作日的下班時間、週末、節假日等。由於是第一次接觸這麼系統又這麼底層的知識,從一開始惡補Linux核心知識,到後來系統地學習Android系統的專用驅動、HAL層和應用程式架構層等知識期間,遇到的困難是可想而知的。以致於在花了兩年的時間,完成Android系統研究的第一階段任務之後,忍不住寫了一篇文章《2012年的Android之旅:夢想、學習、堅持、自信、淡定》總結這段學習經歷。就像文章所說的,那兩年學習Android的心得和體會總結起來就是十個字:夢想、學習、堅持、自信、淡定。由於篇幅關係,這裡就不一一展開來說了。不過,我最想分享還是關於堅持這一點。

堅持這兩個字真的是說起來容易做起來難。哪怕是一件很簡單的事情,要求日復一日地堅持去做,恐怕也是不少人做不到的。舉個例子說,鍛鍊身體。我們不說每天,就說每一個星期拿出一個到一個半小時去鍛鍊,又有多少個人能堅持做到的呢?這還是花時間去做就能完成的,不會遇到諸如學習、工作、生活上的挑戰。所以我們說堅持就是勝利,是很有道理的。只要制定好了目標,就一定要下定決心堅持去完成,無論中間遇到什麼樣的困難和挑戰。當堅持變成一種習慣的時候,離目標的實現就不遠了。換句話說,主要你肯堅持,你就會發現:1、你的目標實現了;2、你養成了一種良好的習慣。

經常聽到有人說,太難了,看/學/做不下去了。其實,沒有什麼事情是與生俱來就會的。既然是不會的,學習的過程就肯定要付出代價。2010年下半年之前,我平時學習、工作、和娛樂基本上都是在Windows平臺上,第一次學習Linux核心看的是《Linux核心原始碼情景分析》 這本書。看過這本書的人都知道,那基本上就是一本天書。當時我對自己說,不緊要,看一遍不懂,我就再看第二遍、第三遍和第四遍。最後執行的過程是,看過第一遍後,心裡只是大概有個譜。接著去找一些相關的經典書籍來繼續看,例如《Linux核心設計與實現》。看完了《Linux核心設計與實現》,回過頭來又接著第二遍看《Linux核心原始碼情景分析》。這下就發現原來一些看不懂的地方現在懂了,但是還是有其它地方看不懂。於是,又繼續看了《Linux裝置驅動程式》和《深入理解Linux核心》等書。每次覺得有必要的時候,都又重新去看一遍《Linux核心原始碼情景分析》。經過這樣的三四遍折騰之後,最後終於可以很愉快地看懂《Linux核心原始碼情景分析》了。

當然,除了有毅力去堅持之外,還要懂得堅持的方法。借用馬丁·路德·金的一句話:

If you can’t fly, then run; if you can’t run, then walk; if you can’t walk, then crawl, but whatever you do, you have to keep moving forward。

這句話我覺得重點就是最後三個單詞“keep moving forward”。在堅持的過程中,你要讓自己覺得自己一直在“keep moving forward”,這樣才會有堅持下去的動力。換句話說,就是要讓自己在堅持的過程中看得到事情又推進了一步,哪怕是一點點的進步。還是以看書為例子。只要你每天堅持平均看20頁,一年就可以看7300頁。打個8折,也有5840頁,也相當於10本書了。10本書看下來,可以學到的東西是相當多的了。在這個過程中,每天看20頁書這件事就是推你向前了一步。有人可能覺得每天看20頁書還是太難了。是的,開始的時候可能是有點難。但是,當你堅持一段時間之後,就會發現瞭解的知識變多之後,看書的速度也跟著加快,到時候不要說一天20頁,一天50頁都不是問題。

CSDN:你是《Android系統原始碼情景分析》(試讀地址)一書的作者,這本書是怎樣誕生的?這是你的第一本書,寫書過程中經歷了怎樣的困難?隨著Andriod的版本更迭,你會出第二版嗎?還有其它著書計劃嗎?

羅昇陽:一開始只是想通過部落格記錄自己學習Android系統的過程,並沒有計劃寫書的。隨著部落格的人氣上升,不斷有出版社編輯發出出書的邀請。開始的時候,基本上還是拒絕的。再到後來,也有不少網友建議把部落格整理一下成書出版。在出版社和網友的多次建議下,也考慮到有些讀者可能更喜歡閱讀紙質書,最終就決定把部落格的文章整理成書出版了。

第一次寫書,懷著的是誠惶誠恐的心情,擔心能力有限,誤人子弟。書與部落格不一樣,出書包含有出版社、渠道和銷售等成本,因此讀者是不可能免費得到的。既然讀者要付出錢來購買你的書,那你寫書的時候就得負起責任,例如要保證內容的系統性、完整性和正確性,還有文字表達的通順性,甚至還不能出現錯別字。這與在網上寫部落格有很大的區別。寫部落格可以比較隨意一點,漏掉的內容可以以後再補,錯誤字也可以馬上就修改過來。

基於面這些原因,寫書過程經歷的困難是可想而知的。決定寫書之後,一開始並沒有急著去寫,而是將計劃綱入書裡面的內容都先發表到部落格上,也就是我在2011年12月前發表的文章。主要是考慮到先將內容發表出來,讓讀者看到之後可以幫忙發現BUG以及提建議,這樣可以幫助提高書的質量。整理部落格不是簡單的拷貝貼上,比我想象中要困難多了。回過頭來再看自己發表過的文字,百分之七八十都要重新表達。而且有些章節,要系統地描述清楚,單靠部落格上的文章是遠遠不夠的。例如,在寫Binder那一章時,原以為在部落格寫的一系列文章已經夠完備了,但是發現只是寫了一半不到。然後就拼命地一邊整理已有的內容,並且一邊補新的內容。

在時間上,從開始整理到出版的半年時間裡,除了工作基本就是撲在寫書上了,而且利用的都是工作之餘的時間。沒有周末,沒有節假日,工作日也是經常熬夜到兩三四點。對程式設計師來說,寫文字其實比寫程式碼要累多了,這就是為什麼程式設計師都不喜歡給自己的程式碼寫文件寫註釋的原因。期間是想過要放棄的,但是已經跟出版社簽定了合同,怎麼都堅持下去啊。就這樣一路走來,從部落格文章整理得到初稿,又經過三遍逐行逐行的校對,終於完成了三大篇十六章830頁近160萬字的著作。說實話,當時要是再讓我看第四遍的時候,感覺都要吐了。

Android版本更新的確是比較快,不過目前是沒有出第二版的計劃了。主要是因為我寫的內容都是很基礎的東西,例如HAL、Binder IPC、Ashmem、Logger,以及四大元件Activity、Service、Broadcast Receiver和Content Provider的實現原理,它們在後來的版本中仍然是保持性當初的設計思想和執行原理的。我更希望的是,讀者看了我的書之後,能夠自己去分析Android系統的原始碼,這樣以後Android版本更新得再快也不怕了。

至於新書,以前是有計劃的。完成了《Android系統原始碼情景分析》一書之後,我又陸續在部落格了發表了UI架構、UI渲染、視窗管理、Dalvik虛擬機器、編譯系統、SEAnroid安全機制等一系列的文章。這些內容加起來也可以有《Android系統原始碼情景分析》這本書那麼厚了。不過寫書是費時費力的事情,而且產出投入比也不高,再加我也不是專職的圖書作家,所以現在也不打算出新書了。但是部落格是一定會堅持寫下去的,希望讀者可以持續關注,並且可以在部落格上與我交流。

CSDN:初學Android的時候,很多人搞不清Android和Java到底有什麼不同,你認為他們之間的區別是什麼呢?另外,Android核心跟linux又有什麼區別?

羅昇陽:實際上,Android是Android,Java是Java。不用Java,用C/C++寫的程式,也一樣可以在Android上執行。對於這個問題,其實不只是初學者,對於不少有經驗的開發者,也會認為做Android應用開發,懂Java就行了。從最近面試的一些人來看,就很明顯地感覺到這個問題的普遍性。很多Android應用開發者只懂得使用Android SDK提供的Java介面來開發東西,但是沒有進一步去學習一些更深層次的東西。

本質上說,Android是一個Linux系統,因此它是基於Linux核心開發的。但是Android與一般的Linux系統不同的是,它有著自己的一套獨特的使用者空間執行時,也就是我們通常說的應用程式框架。舉個例子來說,以前很多基於Linux的嵌入式開發,就是移植一個Linux核心,然後再用Qt作為應用程式框架,這樣一個系統就跑起來了。因此,將Qt應用程式框架替換為Android自己的應用程式框架,就得到了一個現代化的移動作業系統。

在Android應用程式框架中,包含了很多開源工程,例如瀏覽器用的核心WebKit、管理Wi-Fi網路的wap_supplicant、播放音樂視訊的StageFright等,它們都是使用C/C++來寫的。而且Android系統專用的用來渲染UI的SurfaceFlinger、用來播放聲音的AudioFlinger等,也是用C/C++來寫的。更不用提每一個應用程式都要使用到C庫bionic、Dalvik虛擬機器等了,它們都是用C/C++來寫的。這些使用C/C++寫的服務,實現了最基本的功能。這些最基本的功能被在Java層的提供的關鍵服務所使用,例如元件管理服務ActivityManagerService、應用程式安裝服務PackageManagerService、網路連線服務ConnectivityService等。最後,Android再封裝了一套基於Java語言的SDK給開發者去使用那些實現在Java層的系統服務。

也就是說:Android系統=Linux核心+Android使用者空間執行時+ Android SDK,而Android使用者空間執行時=C/C++ Runtime Framework + Java Runtime Framework。很多情況下,我們呼叫Android SDK提供的一個API時,這個API呼叫會交給Java Runtime Framework處理,而Java Runtime Framework又繼續將這個API呼叫交給C/C++ Runtime Framework處理,最後C/C++ Runtime Framework又有可能接著將這個API呼叫交給Linux核心來處理。

從上面的呼叫過程就可以看出,Java只是位於Android最上面的一層程式設計介面,而沒有這一層程式設計介面Android也是可以正常執行的。我們知道,Android除了提供SDK外,還提供有NDK。也就是說,我們完全可以不使用SDK,而是通過NDK提供的介面繞過Java Runtime Framework,直接將請求交給C/C++Runtime Framework處理。

至於Android系統使用的Linux核心,其實與傳統的Linux核心並無多大區別,甚至可以看成是一樣的。要說真的區別,就是有兩點。一是Android在傳統的Linux核心中以模組的形式加入了一些專用的驅動,例如日誌驅動Logger、匿名共享記憶體驅動Ashmem、程序間通訊驅動Binder。二是Android系統將在傳統的Linux核心實現的硬體驅動程式劃分成了兩部分,一部分在核心實現,另一部分在使用者空間實現,也就是我們常說的硬體抽象層HAL。Android系統之所以要這樣劃分,是出於商業考慮,而不是技術考慮。因為Linux核心使用的GPL許可協議,驅動全部放在核心實現就意味著需要全部開原始碼,而使用者空間使用的是Apaache License,可以不開原始碼。通過這種方式,就可以保護廠家的商業利益,因為這些程式碼通常都會包含有硬體的相關引數。

CSDN:Android系統層次結構是怎樣的?各個層之間關係是什麼?

羅昇陽:上面也提到了Android系統的層次,詳細一點說,就是:Android = Linux Kernel + C/C++ Runtime Framework + Davik Virtual Machine + Java Runtime Framework + Java SDK。下面我們再以APK的開發、編譯、安裝和執行來說明這些層次之間的關係。

首先,我們是在PC上使用Android SDK提供的介面來開發APK,用的Java語言。開發完成之後,使用Java編譯器將原始碼編譯成Java位元組碼,也就是帶.class字尾的檔案。接下來這些.class再被Android SDK提供的dx工具轉化成Dex位元組碼,最後打包在APK裡面的classes.dex檔案中。

接著,APK檔案在手機上安裝時,Java Runtime Framework裡面的PacakgeManagerService就會對該APK檔案進行解析,並且通過Socket IPC通知C/C++ Runtime Framework裡面的installd守護程序對APK裡面的classes.dex檔案進行優化,得到另外一個classes.odex檔案。

APK安裝完成之後,就可以運行了。我們以APK從桌面Launcher啟動的過程為例說明它的執行過程。當我們從Launcher點選應用圖示的時候,Launcher向Java Runtime Framework裡面的ActivityManagerService傳送一個啟動應用的請求。ActivityManagerService又通過Socket IPC向C/C++ Runtime Framework裡面的zygote守護程序請求建立一個應用程式程序。這個應用程式程序包含有一個Dalvik虛擬機器。應用程式程序建立並且啟動起來之後,就會通過它裡面的Dalvik虛擬機器載入前面提到的classes.odex檔案。這樣我們的應用程式就執行起來了。

APK的執行過程是依賴於Dalvik虛擬機器的。我們可以將它看成是將classes.odex裡面的位元組碼解釋成本地機器指令執行。例如,我們在APK裡面通過FileInputStream或者FileOutputStream開啟一個檔案的時候,Dalvik虛擬機器就會找到C/C++ Runtime Framework裡面的C庫bionic提供的系統介面open,並且通過它來開啟指定的檔案。

我們再以應用程式介面的繪製和渲染過程來詳細說明各個層次的關係。首先是應用程式通過SDK提供的UI類向Java Runtime Framework裡面的WindowManagerService申請分配一塊圖形緩衝區。WindowManagerService又是通過Binder IPC向C/C++ Runtime Framework裡面的SurfaceFlinger申請分配圖形緩衝區的。圖形緩衝區實際上不是由SurfaceFlinger分配的,而是由顯示系統分配的,可能在視訊記憶體裡面,也有可能在GPU裡面。這時候SurfaceFlinger就要通過HAL層次Gralloc模組向Kernel裡面的顯示卡或者GPU驅動申請分配真正的圖形緩衝區。HAL層可以看作是執行在C/C++ Runtime Framework中。

應用程式得通過上述方式得到繪製UI所需要的圖形緩衝區之後,就開始繪製自己的UI了。假設應用程式使用的是硬體繪製方式,也就是通過C/C++ Runtime Framework裡面的OpenGL來繪製。這時候SDK的UI類的與繪製相關的函式呼叫通過Dalvik虛擬機器都轉化成了C/C++ Runtime Framework裡面的OpenGL操作。

應用程式UI繪製完成之後,結果就儲存上述的圖形緩衝區中。這時候如果要將該圖形緩衝區渲染到手機螢幕上,那麼還需要通過Binder IPC將該圖形緩衝區傳送給C/C++ Runtime Framework裡面的SurfaceFlinger。SurfaceFlinger通過使用OpenGL或者HWComposer將所有請求要渲染到手機螢幕上的圖形緩衝區合成之後,得到一個主圖形緩衝區。最後這個圖形緩衝區又會被SurfaceFlinger提交給Kernel的顯示卡驅動,並且在手機螢幕上進行顯示。

上面描述的就是Android系統各個層次的呼叫關係。總的來說,應用程式執行在Dalvik虛擬機器上,並且通過SDK使用Java Runtime Framework裡面的服務,而Java Runtime Framework裡面的服務又通過C/C++ Runtime Framework裡面的服務來實現自己的功能,最後C/C++ Runtime Framework裡面的服務又會在需要的時候請求Kernel裡面的模組或者驅動來為自己服務。

CSDN:Andriod可以說是開源的代名詞,一些開發者為了保護自己的成果進行加密,而另一些開發者為了學習,需要進行APK反編譯,可以分享下您對加密和反編譯的看法嗎?

羅昇陽:嚴格來說,Android系統是開放不是開源。Linux核心才是嚴格意義上的開源。只要是執行在Linux核心裡面的程式碼,都可以要求作者將程式碼開源出來。但是執行在Android系統使用者空間的程式碼,作者就不需要將它們開源出來了。這些程式碼包括廠商對Android官方原始碼的修改,以及自己增加的程式碼,還有第三方為之開發的APK程式碼等。這是由於Linux核心使用的是GPL許可協議,而Android系統的使用者空間程式碼使用的Apache許可協議。

我覺得無論是開發者為了保護自己的成果而對APK進行加密,還是另一些開發者為了學習而反編譯別人的APK,都是無可厚非的。當然前提是不要利用這些技術去做壞事,否則的話,就是違反法律的事情了。加密和反編譯實際上是一種技術競爭關係。我們都知道,競爭其實是可以推進技術進步的,而技術進步的最終結果對使用者是有好處的。

我在這兩個講《Android安全機制》《APK防反編譯技術》的PPT中,有描述過通過DEX和SO加殼、新增非法指令、隱藏敏感程式碼和偽APK加密技術等辦法來保護程式碼的方法。然而,再厲害的保護技術,只要計算機知識牢固,並且有足夠的耐心,再加上一些工具,例如apktool和ida,都是夠破解的。當然,在別人破解了你現在的保護技術之後,你可以再發明另外的技術來保護自己的程式碼。這就是技術競爭,比的是各自的技術水平。

CSDN:深入理解框架層,需要具備哪些知識?對於開發應用具體有什麼好處?而開發者在學習這一過程中應注意哪些問題?

羅昇陽:從上面對Android系統的描述可以知道,要學入去學習Android系統的框架,需要具備的知識是不少的。

從語言層面來說,需要掌握C、C++、Java,甚至還有彙編。

從系統層面來說,需要有Linux核心基礎,包括程序管理、記憶體管理、檔案系統等,還需要掌握Android的HAL、C/C++ Runtime Framework、Java Runtime Framework和Davivk等。

雖然應用開發者平時不用接觸系統方面的東西,但是如果能夠深入理解Android的框架層,好處是不言而喻的。

首先,可以提高能力和拓寬眼界。因為要看得懂Android系統的程式碼,要求瞭解很多知識。要了解這麼多的知識,又需要不斷地去學習。在學習的過程中,能力和眼界就會自然得到提高和拓寬。

其次,可以正確地使用SDK介面。學習SDK介面,我們一般是通過閱讀SDK文件。但是這些SDK文件只是告訴你它們是怎麼用的,沒有告訴你它們是怎麼實現的。如果我們既知道一個SDK介面是怎麼用的,又知道它是怎麼實現的,那麼用起來肯定會得心應用很多。而且在使用出錯的時候,也能迅速地通過檢查它的實現程式碼來定位原因。

再者,可以有效地解決BUG。當程式執行出錯的時候,系統除了會輸出異常資訊或者Crash資訊之外,通常還有伴隨著一些錯誤日誌輸出。往往這些系統輸出的錯誤日誌包含很豐富的資訊,告訴到底是哪些地方出錯了。但是這些錯誤日誌是由系統輸出的,它們的含義以及輸出條件都是由系統定義的。這時候如果要理解到底是什麼地方出錯了,那就得對系統有一定的理解,甚至需要找到輸出這些日誌的系統程式碼來閱讀一下。

總之就是技多不壓身,學到的東西都是自己的,以後靠這些技術賺到的錢也是自己的。但是前面講到,要學入理解Android系統,需要具備的知識是很多的。基於這個原因,應用開發者最需要注意的問題就是不要被這個問題嚇退。其實是沒有人與生俱來就具備這些知識的,而且知識是無究無盡的,活到老就可以學到老。所以一定要堅持學習,一點一滴的積累,哪些不懂就補哪裡。開始學慢一點沒有關係,等積累到一定程度的時候,就會發現自己的學習能力呈加速度趨勢。

CSDN:移動網際網路如今發展得如火如荼,Android在其中佔居著重要的角色,其發展眾說紛紜, 你如何看待Android的未來?

羅昇陽:Android的發展問題,無非就是與iOS相比,孰優孰劣的問題。目前在移動網際網路上,還找不到第三個可以與Android和iOS抗衡的系統。Android與iOS相比,很多人無非就是覺得:

1. Android UI不夠流暢;
2. Android不夠安全;
3. Android更耗電;
4. Android相容性差。

剛開始的時候,Android UI與iOS相比,流暢性的確是差很多。一方面是因為Android手機參差不齊,有些在硬體配置上確實不如iOS。另一方面確實是Android系統自身的問題。但是我們看到自3.0以來,Android就一直在加強UI流暢性進行努力。Android在3.0在應用程式程序這一側,允許使用硬體繪製UI。在4.1的時候,又通過Project Butter計劃,極大地提高了UI的流暢性。到了L版本,又用ART代替了Dalvik,這意味著應用程式執行時執行的是本地機器指令,而不再是虛擬機器機指令,效能將得到極大的提升。總之,目前在同等硬體配置下,Android的UI流暢性與iOS相比,差距是越來越小了。我們期待ART代替Dalvik之後,兩者可以不相伯仲。

關於安全問題,iOS也有自身的安全問題,例如,每次iOS版本升級後,不也是有人很快就釋出了越獄工具嗎?同時我們也看到,Android在4.3版本,引進了SEAndroid,用來加強其安全性。SEAndroid是美國國家安全域性(NSA)在SELinux的基礎上專門為Android系統開發的,用來保證系統即使在被root的情況下,也能最大限度地保護使用者手機的安全。另一方面我們也看到,由於Android系統是開放的,有很多第三方的安全公司,例如Bluebox,積極地幫忙發現漏洞,以便可以及時進行修復。

加密演算法有一個Kerckhoffs原則:祕密寓於金鑰。意思就是說一個密碼系統的安全性,應該僅僅依靠“金鑰沒有洩漏”這個前提。即使整個系統落到了敵人的手裡,敵人了整個系統的所有細節,但是如果敵人不知道金鑰,你的傳輸還是安全的。無論是在戰爭還是和平時期,不能把保密的希望寄於系統/演算法的保密性,因為機械的可以拆解,軟體的可以看彙編。在這一點上,非公開演算法和公開演算法的區別就體現出來了:公開演算法受全世界的密碼學者研究,經受得考驗;非公開演算法只有除了作者外別人都不知道,可能有很好的攻擊但是作者沒有發現。我想由於Android系統是開源的,而iOS系統是閉源的,它們的安全性之間的比較可以類比於公開和非公開的加密演算法安全性比較。

至於Android的耗電問題,很大程度是由應用程式引起的。由於某些原因,Google官方提供的統一推送服務不能在國內使用,導致了每一個需要網路推送的應用程式都自已在後臺啟用了一個服務,定時地檢查伺服器有沒有新的通知。即使是手機已經休眠了,也會對其進行喚醒進行檢查。這就造成了電量非常大的消耗。iOS有統一的推送服務,並且不允許應用自己設計一套推送服務,因此就可以保證電池的優化使用。為了一定程度上解決這個問題,Android在L版本提供了Job Scheduler服務,用來對齊應用對裝置的喚醒,以達到優化電池使用的目的。

至於Android的相容性,是由於Android系統的開放性造成的。各個廠商都可以將Android原始碼拿過來進行修改,並且跑在硬體配置各不相同的手機上,因此就造成在一個手機上執行得很好的程式,到了另外一個手機上就可能會出現問題。

歸結來講,Android的耗電問題和相容性問題,很大程度都是由於Android的開放性導致的。然而,Android的開放性也正是它的優點所在。回想起上個世紀末期,蘋果計算機與IBM相容PC之爭,我們就會發現,IBM相容PC正是靠開放性打敗了蘋果計算機。當然,今時不同往日,今天依然閉源的iOS和開放的Android,兩者除了在手機之外,在車載、穿戴式裝置、智慧家居方面,也都展開全面的競爭,鹿死誰人還不知。但是,我們現在看到的是,很多創業者,想要做自己的智慧裝置時,第一時間想到的肯定是使用Android系統。這說明Android系統有群眾基礎。我們期望眾人拾柴火焰高,Android的發展越來越好。

CSDN:對於Android開發的學習者,他們如何在競爭如此激烈的移動網際網路環境中提升自己的核心競爭力呢?另外,你能推薦一些書給他們嗎?

羅昇陽:要在激烈的移動網際網路環境中提升自己的核心競爭力,關鍵還是要提到自己的技術水平,最佳的途經就是持續的不斷學習。學習既要有廣度,又要有深度。自己感興趣的知識,一定要深入去研究。其它相關的知識,也要嘗試去有一定的瞭解。

關於學習這個話題,有些人覺得現在用不到的東西就沒有必要去學習,否則就太浪費時間了。其實,很多東西等到要用到的時候再去學,就太遲了。要知道,我們通過學習用到的東西,雖然不會直接反應在我們現在工作的內容上,但是也會潛默移化地響應著我們思考方式,把我們往好的方向推動。還有的就是,我們學的所有東西都不會白白浪費的,總有一天都會派上用場的,特別是在當今十年河東十年河西的科技時代。十年前,火的是傳統網際網路;十年後,輪到移動網際網路上場;再過五年或者十年呢?誰都不知道會怎麼樣,但是隻要我們有技術在手,就能積極擁抱變化。畢竟從技術層面講,無論時代怎麼變化,核心的東西都相通的。

語言類:

  • 《深度探索C++物件模型》,對應的英文版是《Inside C+++ Object Model》
  • 程式編譯、連結、載入類:
  • 《連結器和載入器》,對應的英文版是《Linker and Loader》
  • 《程式設計師的自我修養:連結、裝載和庫》

作業系統類:

  • 《Linux核心設計與實現》,對應的英文版是《Linux Kernel Development》
  • 《深入理解Linux核心》,對應的英文版是《Understanding the Linux Kernel》
  • 《深入Linux核心架構》,對應的英文版是《Professional Linux Kernel Architecture》
  • 《Linux核心原始碼情景分析》

網路類:

  • 《Linux網路體系結構:Linux核心中網路協議的設計與實現》,對應的英文版是《The Linux Networking Architecture: Design and Implementation of Network Protocols in the Linux Kernel》
  • 《深入理解LINUX網路技術內幕》,對應的英文版是《 Understanding Linux Network Internals》

裝置驅動類:

  • 《Linux裝置驅動程式》,對應的英文版是《Linux Device Drivers》
  • 《精通Linux裝置驅動程式開發》,對應的英文版是《Essential Linux Device Drivers》

虛擬機器類:

  • 《Java SE 7虛擬機器規範》
  • 《深入Java虛擬機器》,對應的英文版是《Inside the Java Virtual Machine》
  • 《Oracle JRockit: The Definitive Guide》

嵌入式類:

  • 《嵌入式Linux開發》,對應的英文版是《Embedded Linux Primer》
  • 《構建嵌入式Linux系統》,對應的英文版是《Building Embedded Linux Systems》

ARM體系架構類:

  • 《ARM嵌入式系統開發:軟體設計與優化》,對應的英文版是《ARM System Developer's Guide: Designing and Optimizing System Software》

綜合類:

  • 《深入理解計算機系統》,對應的英文版是《Computer Systems: A Programmer's Perspective》

同時,我自己也是處於不斷的學習中,平時也會看其它比較多的書,大家有興趣的話,可以關注我的新浪微博(@羅昇陽),上面有不定時的推薦。

CSDN:你在CSDN的社群中具有著極高的人氣,部落格專欄“老羅的Android之旅”受到大家的追捧,當初你為何選擇寫部落格?寫部落格給你帶來了什麼好處?

羅昇陽:當初選擇寫部落格,是寫給自己看的,當筆記用。否則如果什麼都不寫的話,研究過的東西很快就忘記了。直到現在,在需要的時候,我都會去翻自己的部落格。隨著部落格讀者越來越多,部落格就不再是給自己當筆記用了,還是一個用來學習交流分享知識,以及結識志同道合的朋友的場所。

不過,我覺得最重要的是,通過發表部落格文章,可以讓對我Android的研究更加嚴謹、更加詳細、更加系統。因為每天這麼多讀者瀏覽你的文章,你就必須要保證文章的質量,否則的話就會誤人子弟,也會毀了自己的名聲。為了寫出有質量的文章,就必須要嚴謹、詳細和系統地去研究Android系統的程式碼。因此,寫部落格和研究Android是一個相互促進的過程。

CSDN:你是什麼時候接觸CSDN的?它對你學習和工作都帶來哪些影響?同時,對CSDN有什麼建議?

羅昇陽:在寫部落格之前,其實是比較少接觸CSDN。2011年6月決定要通過部落格來記錄自己研究Android的歷程時,也嘗試過找其它的部落格網站來寫文章。最後發現CSDN文章貼的程式碼顯示格式使用者體驗挺好的。於是就決定使用CSDN部落格了。

CSDN對學習和工作的影響,最主要的就是它讓我用嚴謹、詳細、系統的方法去研究Android,從而也使得我對Android系統的理解更加深入。

對CSDN的建議,就是希望CSDN可以加強穩定性,以前時不時都會出現訪問不了的情況,不過最近半年情況好像是好一些了。另外一個是加強對移動端的使用者體驗。我看到最近CSDN增加了對移動端的支援,不過在瀏覽個人部落格時,看不到博主的相關資訊,例如瀏覽量、積分、排名和評論等。有時候想看看有沒有新的評論需要回復,看不到就麻煩的,無法與讀者進行交流,而且又不能切換回PC端模式。