摘 要:App2SD(ApplicationtoSDcard)可以將系統(tǒng)中內(nèi)部存儲的部分文件遷移到外部存儲(如SD卡)中,以此來實(shí)現(xiàn)內(nèi)部存儲的“擴(kuò)容”也讓外部存儲空間得到充分利用,本文通過對基本原理和環(huán)境準(zhǔn)備的詳細(xì)說明,將遷移功能在操作系統(tǒng)的層面完成。主要以三星i559手機(jī)為例,描述了實(shí)現(xiàn)App2SD的具體實(shí)現(xiàn)過程,讓手機(jī)獲得真正想要的App2SD功能。
關(guān)鍵詞:Android系統(tǒng);App2SD
中圖分類號:TP311.1
1 應(yīng)用背景
Android從2.2開始已支持App2SD(ApplicationtoSDCARD)的功能,可以將系統(tǒng)中內(nèi)部存儲的部分文件遷移到外部存儲(如SD卡)中,以此來實(shí)現(xiàn)內(nèi)部存儲的“擴(kuò)容”也讓外部存儲空間得到充分利用。當(dāng)下有很多也稱之為App2SD的軟件,但這些軟件都是在應(yīng)用層面將已安裝在內(nèi)部存儲上的軟件移動到外存中去,需要在每次安裝新程序后手工進(jìn)行遷移操作,使用時(shí)較為麻煩且受被遷移軟件特性(某些軟件本身不支持遷移,即便被強(qiáng)制遷移也會讓軟件運(yùn)行不正常)的限制。本文所實(shí)現(xiàn)的內(nèi)容則是要將遷移功能在操作系統(tǒng)的層面完成,通過系統(tǒng)層實(shí)現(xiàn)App2SD功能具有對上層的Android框架完全透明的優(yōu)點(diǎn),讓程序安裝時(shí)將本應(yīng)放置于內(nèi)部存儲的安裝文件自動存放到外存上且不會受安裝程序的限制。其實(shí),即便是2.2以上的系統(tǒng)很多手機(jī)商家也未將該功能直接加到與手機(jī)相配的Android系統(tǒng)中,因此要讓手機(jī)想要真正獲得App2SD的功能就需要在了解其原理的基礎(chǔ)上進(jìn)行手工實(shí)現(xiàn)。
2 基本原理
通常手機(jī)的存儲空間可以分為三個(gè)部分:內(nèi)部RAM、內(nèi)部ROM和外部ROM。內(nèi)部RAM即為內(nèi)存,是CPU運(yùn)算時(shí)數(shù)據(jù)的重要暫存空間;內(nèi)部ROM則是存放操作系統(tǒng)Android的內(nèi)部閃存,如果與一臺裝有windows系統(tǒng)的電腦進(jìn)行類比,可認(rèn)為內(nèi)部ROM是裝有Windows系統(tǒng)的系統(tǒng)盤(通常是C盤),這部分空間由手機(jī)自帶且容量較小;而外部ROM可看作是除系統(tǒng)盤以外的其他磁盤,由外部存儲卡(如SD、TF卡等)組成且容量較大,用于存放照片、音樂等用戶自己的文件。Android可以設(shè)置系統(tǒng)在安裝程序時(shí)將程序安裝在什么位置,通常會有內(nèi)部ROM、外部ROM和由程序自己決定三種選擇,用戶多會選擇“由程序自己決定”方式,而較多程序在開發(fā)時(shí)因結(jié)構(gòu)設(shè)計(jì)以及考慮到程序的快速穩(wěn)定運(yùn)行都需將安裝位置放在內(nèi)部ROM中。但由于內(nèi)部ROM本身容量較?。ㄍǔV挥?00M),因而會出現(xiàn)在安裝多個(gè)軟件后內(nèi)部ROM的容量使用就會處于報(bào)警狀態(tài),而外部ROM的空間卻被大量閑置未被使用的情況。由此提出了將部分外部ROM劃分出來掛載到內(nèi)部ROM上供系統(tǒng)使用。
具體在實(shí)現(xiàn)中需先將外存卡劃分為兩個(gè)分區(qū):一個(gè)為FAT格式仍作為外部ROM使用,另一個(gè)則為EXT格式(通常是ext2或ext3,視系統(tǒng)的識別能力而定)作為掛載分區(qū)。使用EXT格式的原因是防止出現(xiàn)非預(yù)期結(jié)果,否則會有被系統(tǒng)啟動過程中將其當(dāng)作外部ROM進(jìn)行掛載的可能。經(jīng)過分區(qū)并格式化后的外存卡在系統(tǒng)啟動后會在/dev/block中的設(shè)備列表中有所反映:多出一個(gè)mmcblk0p2(mmcblk0是指外存卡設(shè)備,而mmcblk0p1和mmcblk0p2則是其上的兩個(gè)分區(qū))設(shè)備文件。此時(shí)在系統(tǒng)中(考慮到穩(wěn)定與安全性通常會選擇在/system下)創(chuàng)建目錄,將mmcblk0p2以ext格式掛載在該目錄上,從此存放在該目錄中的任何文件實(shí)際上都被存放在了外存卡的第二個(gè)EXT分區(qū)上。接下來便可把與程序安裝有關(guān)的多個(gè)目錄(/data下的app、app-private、dalvik-cache和data)都遷移至EXT分區(qū),當(dāng)然最后還須考慮成功實(shí)現(xiàn)App2SD功能的重要條件:讓系統(tǒng)繼續(xù)使用這些將被遷走的目錄,因此需在/data下為被遷走的目錄建立指向EXT分區(qū)對應(yīng)目錄的鏈接文件。
上述的EXT分區(qū)掛載工作是在系統(tǒng)啟動后手動完成的,但Android重啟后會因?yàn)镋XT分區(qū)沒被掛載使得被遷移的目錄不能訪問最終造成系統(tǒng)不能成功,因此還需要實(shí)現(xiàn)系統(tǒng)啟動時(shí)自動掛載分區(qū)的功能。在系統(tǒng)的根目錄下有一個(gè)init.rc文件可用來控制Android的初始化進(jìn)程完成某些初始化工作,在該文件適當(dāng)?shù)奈恢眉尤肟刂浦噶畋憧勺屜到y(tǒng)啟動時(shí)自動掛載EXT分區(qū)。不過直接修改此文件是不可行的,因?yàn)榇藭r(shí)的init.rc文件只是一副本:手機(jī)的內(nèi)部ROM中留存有一個(gè)啟動鏡像文件boot.img,且此鏡像文件中包含有init.rc,系統(tǒng)啟動時(shí)會把boot.img展開并提取出init.rc并放于根目錄下,初始化進(jìn)程是以這時(shí)產(chǎn)生的init.rc文件作為控制依據(jù)完成初始化工作的,所以在啟動完成后對init.rc文件的編輯操作只是對一個(gè)副本進(jìn)行的,此副本在下次啟動時(shí)將會被覆蓋且不會起到任何作用。然而,boot.img是安裝系統(tǒng)(即常說的“刷機(jī)”)時(shí)被寫入手機(jī)的,之前該文件是與Android系統(tǒng)的其它重要文件(如內(nèi)核文件kernel、恢復(fù)鏡像文件recovery.img、系統(tǒng)結(jié)構(gòu)文件system.rfs等)一并打包作為系統(tǒng)安裝所用的rom文件(常說的刷機(jī)包)而存在的,所以需要把rom包解開后提取并修改當(dāng)中的init.rc文件再封裝成有效的rom文件且刷入手機(jī)才能實(shí)現(xiàn)所需要的初始化控制功能。
3 環(huán)境準(zhǔn)備
3.1 外存分區(qū)
將手機(jī)的SD卡取出插在讀卡器上與電腦相連,通過“AcronisDiskdirectorSuite”軟件將sd卡分成兩個(gè)分區(qū)并進(jìn)行格式化,一個(gè)作為常規(guī)外部ROM(fat32格式,以下稱為FAT分區(qū)),另一個(gè)則存放被遷移的程序文件(ext2格式,以下稱為EXT分區(qū))。EXT分區(qū)應(yīng)根據(jù)自己將安裝的應(yīng)用多少和大小而定(一般在400至500兆),剩下的空間可都分配給FAT分區(qū)使用。需要注意的是,兩個(gè)分區(qū)在創(chuàng)建時(shí)都應(yīng)設(shè)為主分區(qū)類型,且FAT分區(qū)在EXT分區(qū)之前。
3.2 工具軟件
在windows下創(chuàng)建adb與bootimg兩個(gè)文件夾,分別放入adb(AndroidDebugBridge)與bootimg工具軟件。adb用于和手機(jī)間的通信。除了本文所提到的功能以外,更多的adb功能可通過幫助命令“adb-h”獲得;bootimg則用于對boot.img文件進(jìn)行展開和打包操作。
3.3 操作環(huán)境
外存卡插回手機(jī)并與電腦本連,在windows下同時(shí)開啟兩個(gè)控制終端(“cmd”命令)窗口,一個(gè)通過“adbshell”命令與手機(jī)的Linux系統(tǒng)相連,實(shí)現(xiàn)與手機(jī)Linux系統(tǒng)的shell命令交互;另一個(gè)則保持在windowsDOS環(huán)境下完成與手機(jī)間的文件互傳以及boot.img文件的解包和打包。在Linuxshell環(huán)境中,通過“mkdir”命令在/sdcard上建立rom和ramdisk兩個(gè)工作目錄分別用于存放刷機(jī)文件rom.tar和根結(jié)構(gòu)文件ramdisk.gz展開后的文件。
4 實(shí)現(xiàn)過程
本節(jié)開始將以三星i559手機(jī)(Android版本為2.3.5,本身不帶有App2SD功能)為例,將實(shí)現(xiàn)過程進(jìn)行詳細(xì)說明。實(shí)現(xiàn)過程主要分為6個(gè)步驟,對于命令行的描述除了命令本身內(nèi)容外,將以“【L】”和“【W(wǎng)】”開頭來標(biāo)注該命令的運(yùn)行環(huán)境是LinuxShell或是WindowsDOS(參見上一節(jié)),同時(shí)對命令的功能解釋說明用分號“;”作為分隔符放于命令行的后段。
4.1 提取ramdisk文件
本步驟把與三星i559相配的刷機(jī)包文件rom.tar進(jìn)行解包,提取出啟動鏡像文件boot.img,再利用bootimg.exe工具將boot.img文件展開進(jìn)而得到Android根結(jié)構(gòu)的描述文件ramdisk.gz。值得注意的是,展開boot.img文件時(shí),bootimg會將boot.img中的base、cmdline、page_size和padding_size等用于Android系統(tǒng)運(yùn)行所需的配置參數(shù)值顯示于屏幕上,我們可記下這些值以便后面進(jìn)行再封包步驟,從而省去了單獨(dú)對boot.img文件的分析工作。
(1)【W(wǎng)】adbpushrom.tar/sdcard/rom.tar;將刷機(jī)文件放入sdcard卡;(2)【L】cd/sdcard/rom/;變更當(dāng)前目錄;(3)【L】tarxf../rom.tar;展開刷機(jī)文件得到boot.img;(4)【W(wǎng)】cdD:\bootimg\;變更windows下當(dāng)前工作目錄;(5)【W(wǎng)】adbpull/sdcard/rom/boot.img.\boot.img;將boot.img拷到windows中;(6)【W(wǎng)】bootimg--unpack-bootimg;解開boot.img文件,得到ramdisk.gz文件;
說明:第(4)步變換windows下的工作目錄是為了第(5)步拷貝出的boot.img文件與bootimg.exe文件在同一目錄下以便第(6)步能夠正常執(zhí)行。
4.2 解包ramdisk文件獲取init.rc
將上一步驟中得到的ramdisk.gz文件解壓會得到一個(gè)cpio格式的存檔文件,利用cpio命令將存檔文件展開即可得到原始的init.rc。
(1)【W(wǎng)】adbpushramdisk.gz/sdcard/;將ramdisk文件放入sdcard卡;(2)【L】gzip-dramdisk.gz;解壓ramdisk.gz得到cpio格式文件ramdisk;(3)【L】cd/ramdisk;變更工作目錄;(4)【L】cpio-i-F../ramdisk;展開ramdisk文件,得到init.rc文件。
說明:第(2)步在解壓ramdisk.gz文件生成cpio格式的ramdisk文件后原有的ramdisk.gz文件會自動被刪除;第(3)步的工作目錄的目的是為了讓第(4)步展開的所有文件(包括init.rc)存放在/ramdisk下。
4.3 修改init.rc文件
Linux環(huán)境下用vi編輯上一步得到的init.rc文件,在“onpost-fs”節(jié)內(nèi)開始插入“mountext2/dev/block/mmcblk0p2/system/extrw”并保存文件。
4.4 封裝新的rom包并刷入手機(jī)
本步驟主要是第2、3步的逆向過程。將修改后的init.rc文件與其他展開自ramdisk.gz的文件一并重新打包并壓縮生成新的ramdisk.gz文件,再次利用bootimg工具將ramdisk.gz與其他從原boot.img展開得到的文件一并再封裝成新的boot.img文件,最終形成可用于刷機(jī)的rom文件。
(1)【L】find.|cpio-o-Hnewc|gzip>../ramdisk.gz;生成新的ramdisk.gz文件;(2)【W(wǎng)】adbpull/sdcard/ramdisk.gz.\;將新ramdisk.gz拷至windows下;(3)【W(wǎng)】bootimg--repack-bootimgxxx“ccc”yyyzzz;生成新的boot.img文件;(4)【W(wǎng)】adbpushboot.img/sdcard/rom;將新生成的boot.img傳到sdcard卡;(5)【L】cd/sdcard/rom;變更目錄;(6)【L】tarcf../new_rom.tar;在/sdcard下生成新的刷機(jī)rom文件;(7)【W(wǎng)】adbpull/sdcard/new_rom.tar.\;將新rom文件傳入windows;(8)【W(wǎng)】adbrebootdownload;重啟手機(jī)并進(jìn)入刷機(jī)模式
說明:第(1)步須在/sdcard/ramdisk下進(jìn)行;第(2)步拷貝出的ramdisk.gz文件應(yīng)與bootimg.exe文件放置在同一目錄下覆蓋原有的ramdisk.gz文件;第(3)步命令中的xxx、ccc、yyy和zzz分別對應(yīng)于第2步驟中記錄的base、cmdline、page_size和padding-size參數(shù)值;第(4)步將把/sdcard/rom中原有的boot.img文件覆蓋;第(6)步執(zhí)行后會在/sdcard中看到新生成的刷機(jī)包new_rom.tar;在第(8)步后便可利用刷機(jī)工具將新的rom包刷入手機(jī)。
4.5 Android環(huán)境調(diào)整
手機(jī)在刷機(jī)完成并重新啟動后,新的init.rc文件將開始被系統(tǒng)使用。接下來的工作是在系統(tǒng)中建立掛載EXT分區(qū)用的目錄、遷移相關(guān)目錄以及建立鏈接文件。本步驟進(jìn)行前,需先通過mount命令對/system目錄進(jìn)行讀寫重掛載,否則將不能在/system建立掛載所用的目錄,但因各手機(jī)機(jī)型的不同對/system的掛載點(diǎn)也不同,故此處不作說明。對/system的可寫掛載也可利用手機(jī)上的某些軟件(如RootExplorer)來實(shí)現(xiàn),但無論哪種方法都須先對新裝入的Android系統(tǒng)進(jìn)行“root”(獲取root權(quán)限)操作。
(1)【L】mkdir/system/ext;創(chuàng)建掛載EXT分區(qū)用的目錄;(2)【L】chmod775/system/ext;設(shè)置目錄的訪問權(quán)限;(3)【L】chownroot/system/ext;設(shè)置目錄的屬主;(4)【L】chgrproot/system/ext;設(shè)置目錄的屬組;(5)【L】mount-r-w-text2/dev/block/mmcblk0p2/system/ext;手工掛載ext2分區(qū)到/system/ext上;(6)【L】busyboxcp-a/data/xxx/system/ext/;將被遷移目錄拷貝到ext2分區(qū);(7)【L】busyboxrm-rf/data/xxx;刪除/data下的被遷移目錄(8)【L】busyboxln-s/system/ext/xxx/data/xxx;建立/data下各被遷移的目錄相應(yīng)的軟鏈接并指向/system/ext下對應(yīng)的目錄。
說明:因?yàn)樽罱K要將/data中的內(nèi)容遷移到/system/ext目錄中,所以第(2)、(3)、(4)步對ext目錄的屬性設(shè)置都以/data為參照;第(5)步對設(shè)備的手工掛載是因?yàn)?system/ext是在新rom刷入手機(jī)后被建立的,所以新rom中init.rc的自動掛載還不能起作用;第(6)、(7)、(8)步命令中的xxx指代/data目錄下app、app-private、dalvik-cache、data等需要被遷移的目錄。
5 結(jié)論
本文主要以三星i559手機(jī)為例,描述了實(shí)現(xiàn)App2SD的具體實(shí)現(xiàn)過程。但文章所講述的內(nèi)容并不可能完全適用于各種型號與系統(tǒng)版本的手機(jī),應(yīng)用者需根據(jù)自己的硬件與軟件條件進(jìn)行調(diào)整與優(yōu)化。同時(shí)本文所提出的實(shí)現(xiàn)方法還有待改進(jìn)與完善,比如當(dāng)系統(tǒng)在運(yùn)行時(shí)如果外存卡有拔插操作(如人為取出并通過讀卡器與電腦進(jìn)行數(shù)據(jù)交換),而在被Android再識別時(shí)外存卡其對應(yīng)的設(shè)備文件可能會發(fā)生變化(從mmcblk0變成mmcblk1),從而導(dǎo)致原來掛載于mmcblk0p2上的EXT分區(qū)不再可用最終造成系統(tǒng)的不正常運(yùn)行,所以作為穩(wěn)定可靠的方法還應(yīng)加入監(jiān)測功能,根據(jù)外存卡的實(shí)際狀態(tài)動態(tài)獲取相應(yīng)的設(shè)備文件并自動進(jìn)行“再”掛載操作。
參考文獻(xiàn):
[1]android系統(tǒng)啟動流程分析.http://blog.csdn.net/sincethen/article/details/5942472.
[2]Android啟動流程代碼分析.http://wenku.baidu.com/view/571d010716fc700abb68fc28.html.
[3]android系統(tǒng)app2sd(修改boot.img).http://www.cnblogs.com/mahang/archive/2011/09/04/2166066.html.
作者單位:中國人民解放軍裝甲兵工程學(xué)院訓(xùn)練部信息管理中心,北京 100072