轉自:http://mp.weixin.qq.com/s?__biz=MzI3NzA5MzUxNA==&mid=415711810&idx=1&sn=de8337e627811f8a4c8acce2f426f4ad&scene=0#wechat_redirect
專訪羅升陽:老羅的Android之旅
2016-01-16 錢曙光 Linux核心之旅
【編者按】我們常說的智能手機實際上就是手機上加了一個作業系統,那麼大部分人都會跟我一樣不禁發問,這個作業系統和我們接觸更多的電腦上的作業系統一樣嗎。道家雲,看山是山,看山不是山,看山還是山。這三個境界同樣适用于前邊的問題,你說是不是。
羅升陽(部落格),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開發的學習者,他們如何在競争如此激烈的移動網際網路環境中提升自己的核心競争力呢?另外,你能推薦一些書給他們嗎?
羅升陽:要在激烈的移動網際網路環境中提升自己的核心競争力,關鍵還是要提到自己的技術水準,最佳的途經就是持續的不斷學習。學習既要有廣度,又要有深度。自己感興趣的知識,一定要深入去研究。其它相關的知識,也要嘗試去有一定的了解。
關于學習這個話題,有些人覺得現在用不到的東西就沒有必要去學習,否則就太浪費時間了。其實,很多東西等到要用到的時候再去學,就太遲了。要知道,我們通過學習用到的東西,雖然不會直接反應在我們現在工作的内容上,但是也會潛默移化地響應着我們思考方式,把我們往好的方向推動。還有的就是,我們學的所有東西都不會白白浪費的,總有一天都會派上用場的,特别是在當今十年河東十年河西的科技時代。十年前,火的是傳統網際網路;十年後,輪到移動網際網路上場;再過五年或者十年呢?誰都不知道會怎麼樣,但是隻要我們有技術在手,就能積極擁抱變化。畢竟從技術層面講,無論時代怎麼變化,核心的東西都相通的。
要推薦的書,我在《那兩年煉就的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部落格了。