|  1. 顯示系統(tǒng)中全部Android平臺(tái):  android list targets 2. 顯示系統(tǒng)中全部AVD(模擬器): android list avd 3. 創(chuàng)建AVD(模擬器): android create avd --name 名稱 --target 平臺(tái)編號(hào) 4. 啟動(dòng)模擬器: emulator -avd 名稱 -sdcard ~/名稱.img (-skin 1280x800) 5. 刪除AVD(模擬器): android delete avd --name 名稱 6. 創(chuàng)建SDCard: mksdcard 1024M ~/名稱.img 7. AVD(模擬器)所在位置: Linux(~/.android/avd) Windows(C:\Documents and Settings\Administrator\.android\avd) 8. 啟動(dòng)DDMS: ddms 9. 顯示當(dāng)前運(yùn)行的全部模擬器: adb devices 10. 對(duì)某一模擬器執(zhí)行命令: abd -s 模擬器編號(hào) 命令 11. 安裝應(yīng)用程序: adb install -r 應(yīng)用程序.apk 12. 獲取模擬器中的文件: adb pull <remote> <local> 13. 向模擬器中寫(xiě)文件: adb push <local> <remote> 14. 進(jìn)入模擬器的shell模式: adb shell 15. 啟動(dòng)SDK,文檔,實(shí)例下載管理器: android 16. 缷載apk包: adb shell cd data/app rm apk包 exit adb uninstall apk包的主包名 adb install -r apk包 17. 查看adb命令幫助信息: adb help 18. 在命令行中查看LOG信息: adb logcat -s 標(biāo)簽名 19. adb shell后面跟的命令主要來(lái)自: 源碼\system\core\toolbox目錄和源碼\frameworks\base\cmds目錄。 20. 刪除系統(tǒng)應(yīng)用: adb remount (重新掛載系統(tǒng)分區(qū),使系統(tǒng)分區(qū)重新可寫(xiě))。 adb shell cd system/app rm *.apk 21. 獲取管理員權(quán)限: adb root 22. 啟動(dòng)Activity: adb shell am start -n 包名/包名+類名(-n 類名,-a action,-d date,-m MIME-TYPE,-c category,-e 擴(kuò)展數(shù)據(jù),等)。 23、發(fā)布端口: 你可以設(shè)置任意的端口號(hào),做為主機(jī)向模擬器或設(shè)備的請(qǐng)求端口。如: adb forward tcp:5555 tcp:8000 24、復(fù)制文件: 你可向一個(gè)設(shè)備或從一個(gè)設(shè)備中復(fù)制文件, 復(fù)制一個(gè)文件或目錄到設(shè)備或模擬器上: adb push <source> <destination></destination></source> 如:adb push test.txt /tmp/test.txt 從設(shè)備或模擬器上復(fù)制一個(gè)文件或目錄: adb pull <source> <destination></destination></source> 如:adb pull /addroid/lib/libwebcore.so . 25、搜索模擬器/設(shè)備的實(shí)例: 取得當(dāng)前運(yùn)行的模擬器/設(shè)備的實(shí)例的列表及每個(gè)實(shí)例的狀態(tài): adb devices 26、查看bug報(bào)告: adb bugreport 27、記錄無(wú)線通訊日志: 一般來(lái)說(shuō),無(wú)線通訊的日志非常多,在運(yùn)行時(shí)沒(méi)必要去記錄,但我們還是可以通過(guò)命令,設(shè)置記錄: adb shell logcat -b radio 28、獲取設(shè)備的ID和序列號(hào): adb get-product adb get-serialno 29、訪問(wèn)數(shù)據(jù)庫(kù)SQLite3 adb shell sqlite3 busybox BusyBox 是標(biāo)準(zhǔn) Linux 工具的一個(gè)單個(gè)可執(zhí)行實(shí)現(xiàn)。BusyBox 包含了一些簡(jiǎn)單的工具,例如 cat 和 echo,還包含了一些更大、更復(fù)雜的工具,例如 grep、find、mount 以及 telnet。有些人將 BusyBox 稱為 Linux 工具里的瑞士軍刀.簡(jiǎn)單的說(shuō)BusyBox就好像是個(gè)大工具箱,它集成壓縮了 Linux 的許多工具和命令。 1、 BusyBox 的誕生 BusyBox 最初是由 Bruce Perens 在 1996 年為 Debian GNU/Linux 安裝盤(pán)編寫(xiě)的。其目標(biāo)是在一張軟盤(pán)上創(chuàng)建一個(gè)可引導(dǎo)的 GNU/Linux 系統(tǒng),這可以用作安裝盤(pán)和急救盤(pán)。 2、busybox的用法 可以這樣用busybox #busybox ls 他的功能就相當(dāng)運(yùn)行l(wèi)s命令 最常用的用法是建立指向busybox的鏈接,不同的鏈接名完成不同的功能. #ln -s busybox ls #ln -s busybox rm #ln -s busybox mkdir 然后分別運(yùn)行這三個(gè)鏈接: #./ls #./rm #./mkdir 就可以分別完成了ls rm 和mkdir命令的功能.雖然他們都指向同一個(gè)可執(zhí)行程序busybox,但是只要鏈接名不同,完成的功能就不同,很多l(xiāng)inux網(wǎng)站都提供busybox的源代碼下載。 3、配置busybox busybox的配置程序和linux內(nèi)核菜單配置方式簡(jiǎn)直一模一樣.熟悉用make menuconfig方式配置linux內(nèi)核的朋友很容易上手. #cp busybox-1.00.tar.gz /babylinux #cd /babylinux #tar xvfz busybox-1.00.tar.gz #cd busybox-1.00 #make menuconfig 下面是需要編譯進(jìn)busybox的功能選項(xiàng)。 General Configuration應(yīng)該選的選項(xiàng) Show verbose applet usage messages Runtime SUID/SGID configuration via /etc/busybox.conf Build Options Build BusyBox as a static binary (no shared libs) 這個(gè)選項(xiàng)是一定要選擇的,這樣才能把busybox編譯成靜態(tài)鏈接的可執(zhí)行文件,運(yùn)行時(shí)才獨(dú)立于其他函數(shù)庫(kù).否則必需要其他庫(kù)文件才能運(yùn)行,在單一個(gè)linux內(nèi)核不能使它正常工作. Installation Options Don't use /usr 這個(gè)選項(xiàng)也一定要選,否則make install 后busybox將安裝在原系統(tǒng)的/usr下,這將覆蓋掉系統(tǒng)原有的命令.選擇這個(gè)選項(xiàng)后,make install后會(huì)在busybox目錄下生成一個(gè)叫_install的目錄,里面有busybox和指向它的鏈接. 其它選項(xiàng)都是一些linux基本命令選項(xiàng),自己需要哪些命令就編譯進(jìn)去,一般用默認(rèn)的就可以了,配置好后退出并保存。 4、編譯并安裝busybox #make #make install 編譯好后在busybox目錄下生成子目錄_install,里面的內(nèi)容: drwxr-xr-x 2 root root 4096 11月 24 15:28 bin rwxrwxrwx 1 root root 11 11月 24 15:28 linuxrc -> bin/busybox drwxr-xr-x 2 root root 4096 11月 24 15:28 sbin 其中可執(zhí)行文件busybox在bin目錄下,其他的都是指向他的符號(hào)鏈接. Android系統(tǒng)在超級(jí)終端下必會(huì)的命令大全(二) 一、安裝和登錄命令 reboot 1.作用 reboot命令的作用是重新啟動(dòng)計(jì)算機(jī),它的使用權(quán)限是系統(tǒng)管理者。 2.格式 reboot [-n] [-w] [-d] [-f] [-i] 3.主要參數(shù) -n: 在重開(kāi)機(jī)前不做將記憶體資料寫(xiě)回硬盤(pán)的動(dòng)作。 -w: 并不會(huì)真的重開(kāi)機(jī),只是把記錄寫(xiě)到/var/log/wtmp文件里。 -d: 不把記錄寫(xiě)到/var/log/wtmp文件里(-n這個(gè)參數(shù)包含了-d)。 -i: 在重開(kāi)機(jī)之前先把所有與網(wǎng)絡(luò)相關(guān)的裝置停止。 mount 1.作用 mount命令的作用是加載文件系統(tǒng),它的用權(quán)限是超級(jí)用戶或/etc/fstab中允許的使用者。 2.格式 mount -a [-fv] [-t vfstype] [-n] [-rw] [-F] device dir 3.主要參數(shù) -h(huán):顯示輔助信息。 -v:顯示信息,通常和-f用來(lái)除錯(cuò)。 -a:將/etc/fstab中定義的所有文件系統(tǒng)掛上。 -F:這個(gè)命令通常和-a一起使用,它會(huì)為每一個(gè)mount的動(dòng)作產(chǎn)生一個(gè)行程負(fù)責(zé)執(zhí)行。在系統(tǒng)需要掛上大量NFS文件系統(tǒng)時(shí)可以加快加載的速度。 -f:通常用于除錯(cuò)。它會(huì)使mount不執(zhí)行實(shí)際掛上的動(dòng)作,而是模擬整個(gè)掛上的過(guò)程,通常會(huì)和-v一起使用。 -t vfstype:顯示被加載文件系統(tǒng)的類型。 -n:一般而言,mount掛上后會(huì)在/etc/mtab中寫(xiě)入一筆資料,在系統(tǒng)中沒(méi)有可寫(xiě)入文件系統(tǒng)的情況下,可以用這個(gè)選項(xiàng)取消這個(gè)動(dòng)作。 4.應(yīng)用技巧 在 Linux和Unix系統(tǒng)上,所有文件都是作為一個(gè)大型樹(shù)(以/為根)的一部分訪問(wèn)的。要訪問(wèn)CD-ROM上的文件,需要將CD-ROM設(shè)備掛裝在文件樹(shù)中的某個(gè)掛裝點(diǎn)。如果發(fā)行版安裝了自動(dòng)掛裝包,那么這個(gè)步驟可自動(dòng)進(jìn)行。在Linux中,如果要使用硬盤(pán)、光驅(qū)等儲(chǔ)存設(shè)備,就得先將它加載,當(dāng)儲(chǔ)存設(shè)備掛上了之后,就可以把它當(dāng)成一個(gè)目錄來(lái)訪問(wèn)。掛上一個(gè)設(shè)備使用mount命令。在使用mount這個(gè)指令時(shí),至少要先知道下列三種信息:要加載對(duì)象的文件系統(tǒng)類型、要加載對(duì)象的設(shè)備名稱及要將設(shè)備加載到哪個(gè)目錄下。 (1)Linux可以識(shí)別的文件系統(tǒng) ◆ Windows 95/98常用的FAT 32文件系統(tǒng):vfat ; ◆ Win NT/2000 的文件系統(tǒng):ntfs ; ◆ OS/2用的文件系統(tǒng):hpfs; ◆ Linux用的文件系統(tǒng):ext2、ext3; ◆ CD-ROM光盤(pán)用的文件系統(tǒng):iso9660。 雖然vfat是指FAT 32系統(tǒng),但事實(shí)上它也兼容FAT 16的文件系統(tǒng)類型。 (2)確定設(shè)備的名稱 在Linux中,設(shè)備名稱通常都存在/dev里。這些設(shè)備名稱的命名都是有規(guī)則的,可以用“推理”的方式把設(shè)備名稱找出來(lái)。例如,/dev/hda1這個(gè) IDE設(shè)備,hd是Hard Disk(硬盤(pán))的,sd是SCSI Device,fd是Floppy Device(或是Floppy Disk?)。a代表第一個(gè)設(shè)備,通常IDE接口可以接上4個(gè)IDE設(shè)備(比如4塊硬盤(pán))。所以要識(shí)別IDE硬盤(pán)的方法分別就是hda、hdb、hdc、 hdd。hda1中的“1”代表hda的第一個(gè)硬盤(pán)分區(qū) (partition),hda2代表hda的第二主分區(qū),第一個(gè)邏輯分區(qū)從hda5開(kāi)始,依此類推。此外,可以直接檢查/var/log/messages文件,在該文件中可以找到計(jì)算機(jī)開(kāi)機(jī)后系統(tǒng)已辨認(rèn)出來(lái)的設(shè)備代號(hào)。 (3)查找掛接點(diǎn) 在決定將設(shè)備掛接之前,先要查看一下計(jì)算機(jī)是不是有個(gè)/mnt的空目錄,該目錄就是專門(mén)用來(lái)當(dāng)作掛載點(diǎn)(MountPoint)的目錄。建議在/mnt里建幾個(gè)/mnt/cdrom、/mnt/floppy、/mnt/mo等目錄,當(dāng)作目錄的專用掛載點(diǎn)。舉例而言,如要掛載下列5個(gè)設(shè)備,其執(zhí)行指令可能如下 (假設(shè)都是Linux的ext2系統(tǒng),如果是Windows XX請(qǐng)將ext2改成vfat): 軟盤(pán) ===>mount -t ext2 /dev/fd0 /mnt/floppy cdrom ===>mount -t iso9660 /dev/hdc /mnt/cdrom SCSI cdrom ===>mount -t iso9660 /dev/sdb /mnt/scdrom SCSI cdr ===>mount -t iso9660 /dev/sdc /mnt/scdr 不過(guò)目前大多數(shù)較新的Linux發(fā)行版本(包括紅旗 Linux、中軟Linux、Mandrake Linux等)都可以自動(dòng)掛裝文件系統(tǒng),但Red Hat Linux除外。 umount 1.作用 umount命令的作用是卸載一個(gè)文件系統(tǒng),它的使用權(quán)限是超級(jí)用戶或/etc/fstab中允許的使用者。 2.格式 unmount -a [-fFnrsvw] [-t vfstype] [-n] [-rw] [-F] device dir 3.使用說(shuō)明 umount 命令是mount命令的逆操作,它的參數(shù)和使用方法和mount命令是一樣的。Linux掛裝CD-ROM后,會(huì)鎖定CD—ROM,這樣就不能用CD- ROM面板上的Eject按鈕彈出它。但是,當(dāng)不再需要光盤(pán)時(shí),如果已將/cdrom作為符號(hào)鏈接,請(qǐng)使用umount/cdrom來(lái)卸裝它。僅當(dāng)無(wú)用戶 正在使用光盤(pán)時(shí),該命令才會(huì)成功。該命令包括了將帶有當(dāng)前工作目錄當(dāng)作該光盤(pán)中的目錄的終端窗口。 exit 1.作用 exit命令的作用是退出系統(tǒng),它的使用權(quán)限是所有用戶。 2.格式 exit 3.參數(shù) exit命令沒(méi)有參數(shù),運(yùn)行后退出系統(tǒng)進(jìn)入登錄界面。 -------------------------------------------------------------------------------- 作者: ☆-☆ 時(shí)間: 2010-6-8 11:52 Android系統(tǒng)在超級(jí)終端下必會(huì)的命令大全(三) 二、文件處理命令 mkdir 1.作用 mkdir命令的作用是建立名稱為dirname的子目錄,與MS DOS下的md命令類似,它的使用權(quán)限是所有用戶。 2.格式 mkdir [options] 目錄名 3.[options]主要參數(shù) -m, --mode=模式:設(shè)定權(quán)限,與chmod類似。 -p, --parents:需要時(shí)創(chuàng)建上層目錄;如果目錄早已存在,則不當(dāng)作錯(cuò)誤。 -v, --verbose:每次創(chuàng)建新目錄都顯示信息。 --version:顯示版本信息后離開(kāi)。 4.應(yīng)用實(shí)例 在進(jìn)行目錄創(chuàng)建時(shí)可以設(shè)置目錄的權(quán)限,此時(shí)使用的參數(shù)是“-m”。假設(shè)要?jiǎng)?chuàng)建的目錄名是“tsk”,讓所有用戶都有rwx(即讀、寫(xiě)、執(zhí)行的權(quán)限),那么可以使用以下命令: $ mkdir -m 777 tsk grep 1.作用 grep命令可以指定文件中搜索特定的內(nèi)容,并將含有這些內(nèi)容的行標(biāo)準(zhǔn)輸出。grep全稱是Global Regular Expression Print,表示全局正則表達(dá)式版本,它的使用權(quán)限是所有用戶。 2.格式 grep [options] 3.主要參數(shù) [options]主要參數(shù): -c:只輸出匹配行的計(jì)數(shù)。 -I:不區(qū)分大小寫(xiě)(只適用于單字符)。 -h(huán):查詢多文件時(shí)不顯示文件名。 -l:查詢多文件時(shí)只輸出包含匹配字符的文件名。 -n:顯示匹配行及行號(hào)。 -s:不顯示不存在或無(wú)匹配文本的錯(cuò)誤信息。 -v:顯示不包含匹配文本的所有行。 pattern正則表達(dá)式主要參數(shù): \:忽略正則表達(dá)式中特殊字符的原有含義。 ^:匹配正則表達(dá)式的開(kāi)始行。 $: 匹配正則表達(dá)式的結(jié)束行。 \:到匹配正則表達(dá)式的行結(jié)束。 [ ]:?jiǎn)蝹€(gè)字符,如[A]即A符合要求 。 [ - ]:范圍,如[A-Z],即A、B、C一直到Z都符合要求 。 。:所有的單個(gè)字符。 * :有字符,長(zhǎng)度可以為0。 正則表達(dá)式是Linux/Unix系統(tǒng)中非常重要的概念。正則表達(dá)式(也稱為“regex”或“regexp”)是一個(gè)可以描述一類字符串的模式(Pattern)。如果一個(gè)字符串可以用某個(gè)正則表達(dá)式來(lái)描述,我們就說(shuō)這個(gè)字符和該正則表達(dá)式匹配(Match)。這和DOS中用戶可以使用通配符 “*”代表任意字符類似。在Linux系統(tǒng)上,正則表達(dá)式通常被用來(lái)查找文本的模式,以及對(duì)文本執(zhí)行“搜索-替換”操作和其它功能。 4.應(yīng)用實(shí)例 查詢DNS服務(wù)是日常工作之一,這意味著要維護(hù)覆蓋不同網(wǎng)絡(luò)的大量IP地址。有時(shí)IP地址會(huì)超過(guò)2000個(gè)。如果要查看nnn.nnn網(wǎng)絡(luò)地址,但是卻忘了第二部分中的其余部分,只知到有兩個(gè)句點(diǎn),例如nnn nn..。要抽取其中所有nnn.nnn IP地址,使用[0-9 ]\{3 \}\.[0-0\{3\}\。含義是任意數(shù)字出現(xiàn)3次,后跟句點(diǎn),接著是任意數(shù)字出現(xiàn)3次,后跟句點(diǎn)。 $grep ’[0-9 ]\{3 \}\.[0-0\{3\}\’ ipfile 補(bǔ)充說(shuō)明,grep家族還包括fgrep和egrep。fgrep是fix grep,允許查找字符串而不是一個(gè)模式;egrep是擴(kuò)展grep,支持基本及擴(kuò)展的正則表達(dá)式,但不支持\q模式范圍的應(yīng)用及與之相對(duì)應(yīng)的一些更加規(guī)范的模式。 dd 1.作用 dd命令用來(lái)復(fù)制文件,并根據(jù)參數(shù)將數(shù)據(jù)轉(zhuǎn)換和格式化。 2.格式 dd [options] 3.[opitions]主要參數(shù) bs=字節(jié):強(qiáng)迫 ibs=及obs=。 cbs=字節(jié):每次轉(zhuǎn)換指定的。 conv=關(guān)鍵字:根據(jù)以逗號(hào)分隔的關(guān)鍵字表示的方式來(lái)轉(zhuǎn)換文件。 count=塊數(shù)目:只復(fù)制指定的輸入數(shù)據(jù)。 ibs=字節(jié):每次讀取指定的。 if=文件:讀取內(nèi)容,而非標(biāo)準(zhǔn)輸入的數(shù)據(jù)。 obs=字節(jié):每次寫(xiě)入指定的。 of=文件:將數(shù)據(jù)寫(xiě)入,而不在標(biāo)準(zhǔn)輸出顯示。 seek=塊數(shù)目:先略過(guò)以obs為單位的指定的輸出數(shù)據(jù)。 skip=塊數(shù)目:先略過(guò)以ibs為單位的指定的輸入數(shù)據(jù)。 4.應(yīng)用實(shí)例 dd命令常常用來(lái)制作Linux啟動(dòng)盤(pán)。先找一個(gè)可引導(dǎo)內(nèi)核,令它的根設(shè)備指向正確的根分區(qū),然后使用dd命令將其寫(xiě)入軟盤(pán): $ rdev vmlinuz /dev/hda $dd if=vmlinuz of=/dev/fd0 上面代碼說(shuō)明,使用rdev命令將可引導(dǎo)內(nèi)核vmlinuz中的根設(shè)備指向/dev/hda,請(qǐng)把“hda”換成自己的根分區(qū),接下來(lái)用dd命令將該內(nèi)核寫(xiě)入軟盤(pán)。 find 1.作用 find命令的作用是在目錄中搜索文件,它的使用權(quán)限是所有用戶。 2.格式 find [path][options][expression] path指定目錄路徑,系統(tǒng)從這里開(kāi)始沿著目錄樹(shù)向下查找文件。它是一個(gè)路徑列表,相互用空格分離,如果不寫(xiě)path,那么默認(rèn)為當(dāng)前目錄。 3.主要參數(shù) [options]參數(shù): -depth:使用深度級(jí)別的查找過(guò)程方式,在某層指定目錄中優(yōu)先查找文件內(nèi)容。 -maxdepth levels:表示至多查找到開(kāi)始目錄的第level層子目錄。level是一個(gè)非負(fù)數(shù),如果level是0的話表示僅在當(dāng)前目錄中查找。 -mindepth levels:表示至少查找到開(kāi)始目錄的第level層子目錄。 -mount:不在其它文件系統(tǒng)(如Msdos、Vfat等)的目錄和文件中查找。 -version:打印版本。 [expression]是匹配表達(dá)式,是find命令接受的表達(dá)式,find命令的所有操作都是針對(duì)表達(dá)式的。它的參數(shù)非常多,這里只介紹一些常用的參數(shù)。 —name:支持統(tǒng)配符*和?。 -atime n:搜索在過(guò)去n天讀取過(guò)的文件。 -ctime n:搜索在過(guò)去n天修改過(guò)的文件。 -group grpoupname:搜索所有組為grpoupname的文件。 -user 用戶名:搜索所有文件屬主為用戶名(ID或名稱)的文件。 -size n:搜索文件大小是n個(gè)block的文件。 -print:輸出搜索結(jié)果,并且打印。 4.應(yīng)用技巧 find命令查找文件的幾種方法: (1)根據(jù)文件名查找 例如,我們想要查找一個(gè)文件名是lilo.conf的文件,可以使用如下命令: find / -name lilo.conf find命令后的“/”表示搜索整個(gè)硬盤(pán)。 (2)快速查找文件 根據(jù)文件名查找文件會(huì)遇到一個(gè)實(shí)際問(wèn)題,就是要花費(fèi)相當(dāng)長(zhǎng)的一段時(shí)間,特別是大型Linux文件系統(tǒng)和大容量硬盤(pán)文件放在很深的子目錄中時(shí)。如果我們知道了這個(gè)文件存放在某個(gè)目錄中,那么只要在這個(gè)目錄中往下尋找就能節(jié)省很多時(shí)間。比如smb.conf文件,從它的文件后綴“.conf”可以判斷這是一個(gè)配置文件,那么它應(yīng)該在/etc目錄內(nèi),此時(shí)可以使用下面命令: find /etc -name smb.conf 這樣,使用“快速查找文件”方式可以縮短時(shí)間。 (3)根據(jù)部分文件名查找方法 有時(shí)我們知道只某個(gè)文件包含有abvd這4個(gè)字,那么要查找系統(tǒng)中所有包含有這4個(gè)字符的文件可以輸入下面命令: find / -name ’*abvd*’ 輸入這個(gè)命令以后,Linux系統(tǒng)會(huì)將在/目錄中查找所有的包含有abvd這4個(gè)字符的文件(其中*是通配符),比如abvdrmyz等符合條件的文件都能顯示出來(lái)。 (4) 使用混合查找方式查找文件 find命令可以使用混合查找的方法,例如,我們想在/etc目錄中查找大于500000字節(jié),并且在24小時(shí)內(nèi)修改的某個(gè)文件,則可以使用-and (與)把兩個(gè)查找參數(shù)鏈接起來(lái)組合成一個(gè)混合的查找方式。 find /etc -size +500000c -and -mtime +1 mv 1.作用 mv命令用來(lái)為文件或目錄改名,或者將文件由一個(gè)目錄移入另一個(gè)目錄中,它的使用權(quán)限是所有用戶。該命令如同DOS命令中的ren和move的組合。 2.格式 mv[options] 源文件或目錄 目標(biāo)文件或目錄 3.[options]主要參數(shù) -i:交互方式操作。如果mv操作將導(dǎo)致對(duì)已存在的目標(biāo)文件的覆蓋,此時(shí)系統(tǒng)詢問(wèn)是否重寫(xiě),要求用戶回答“y”或“n”,這樣可以避免誤覆蓋文件。 -f:禁止交互操作。mv操作要覆蓋某個(gè)已有的目標(biāo)文件時(shí)不給任何指示,指定此參數(shù)后i參數(shù)將不再起作用。 4.應(yīng)用實(shí)例 (1)將/usr/cbu中的所有文件移到當(dāng)前目錄(用“.”表示)中: $ mv /usr/cbu/ * . (2)將文件cjh.txt重命名為wjz.txt: $ mv cjh.txt wjz.txt ls 1.作用 ls命令用于顯示目錄內(nèi)容,類似DOS下的dir命令,它的使用權(quán)限是所有用戶。 2.格式 ls [options][filename] 3.options主要參數(shù) -a, --all:不隱藏任何以“.” 字符開(kāi)始的項(xiàng)目。 -A, --almost-all:列出除了“ . ”及 “.. ”以外的任何項(xiàng)目。 --author:印出每個(gè)文件著作者。 -b, --escape:以八進(jìn)制溢出序列表示不可打印的字符。 --block-size=大小:塊以指定的字節(jié)為單位。 -B, --ignore-backups:不列出任何以 ~ 字符結(jié)束的項(xiàng)目。 -f:不進(jìn)行排序,-aU參數(shù)生效,-lst參數(shù)失效。 -F, --classify:加上文件類型的指示符號(hào) (*/=@| 其中一個(gè))。 -g:like -l, but do not list owner。 -G, --no-group:inhibit display of group information。 -i, --inode:列出每個(gè)文件的inode號(hào)。 -I, --ignore=樣式:不印出任何符合Shell萬(wàn)用字符的項(xiàng)目。 -k:即--block-size=1K。 -l:使用較長(zhǎng)格式列出信息。 -L, --dereference:當(dāng)顯示符號(hào)鏈接的文件信息時(shí),顯示符號(hào)鏈接所指示的對(duì)象,而并非符號(hào)鏈接本身的信息。 -m:所有項(xiàng)目以逗號(hào)分隔,并填滿整行行寬。 -n, --numeric-uid-gid:類似-l,但列出UID及GID號(hào)。 -N, --literal:列出未經(jīng)處理的項(xiàng)目名稱,例如不特別處理控制字符。 -p, --file-type:加上文件類型的指示符號(hào) (/=@| 其中一個(gè))。 -Q, --quote-name:將項(xiàng)目名稱括上雙引號(hào)。 -r, --reverse:依相反次序排列。 -R, --recursive:同時(shí)列出所有子目錄層。 -s, --size:以塊大小為序。 4.應(yīng)用舉例 ls 命令是Linux系統(tǒng)使用頻率最多的命令,它的參數(shù)也是Linux命令中最多的。使用ls命令時(shí)會(huì)有幾種不同的顏色,其中藍(lán)色表示是目錄,綠色表示是可執(zhí) 行文件,紅色表示是壓縮文件,淺藍(lán)色表示是鏈接文件,加粗的黑色表示符號(hào)鏈接,灰色表示是其它格式文件。ls最常使用的是ls- l。 文 件類型開(kāi)頭是由10個(gè)字符構(gòu)成的字符串。其中第一個(gè)字符表示文件類型,它可以是下述類型之一:-(普通文件)、d(目錄)、l(符號(hào)鏈接)、b(塊設(shè)備文件)、c(字符設(shè)備文件)。后面的9個(gè)字符表示文件的訪問(wèn)權(quán)限,分為3組,每組3位。第一組表示文件屬主的權(quán)限,第二組表示同組用戶的權(quán)限,第三組表示其他用戶的權(quán)限。每一組的三個(gè)字符分別表示對(duì)文件的讀(r)、寫(xiě)(w)和執(zhí)行權(quán)限(x)。對(duì)于目錄,表示進(jìn)入權(quán)限。s表示當(dāng)文件被執(zhí)行時(shí),把該文件的UID 或GID賦予執(zhí)行進(jìn)程的UID(用戶ID)或GID(組ID)。t表示設(shè)置標(biāo)志位(留在內(nèi)存,不被換出)。如果該文件是目錄,那么在該目錄中的文件只能被超級(jí)用戶、目錄擁有者或文件屬主刪除。如果它是可執(zhí)行文件,那么在該文件執(zhí)行后,指向其正文段的指針仍留在內(nèi)存。這樣再次執(zhí)行它時(shí),系統(tǒng)就能更快地裝入該文件。接著顯示的是文件大小、生成時(shí)間、文件或命令名稱。 Android系統(tǒng)在超級(jí)終端下必會(huì)的命令大全(四) diff 1.作用 diff命令用于兩個(gè)文件之間的比較,并指出兩者的不同,它的使用權(quán)限是所有用戶。 2.格式 diff [options] 源文件 目標(biāo)文件 3.[options]主要參數(shù) -a:將所有文件當(dāng)作文本文件來(lái)處理。 -b:忽略空格造成的不同。 -B:忽略空行造成的不同。 -c:使用綱要輸出格式。 -H:利用試探法加速對(duì)大文件的搜索。 -I:忽略大小寫(xiě)的變化。 -n --rcs:輸出RCS格式。 cmp 1.作用 cmp(“compare”的縮寫(xiě))命令用來(lái)簡(jiǎn)要指出兩個(gè)文件是否存在差異,它的使用權(quán)限是所有用戶。 2.格式 cmp[options] 文件名 3.[options]主要參數(shù) -l: 將字節(jié)以十進(jìn)制的方式輸出,并方便將兩個(gè)文件中不同的以八進(jìn)制的方式輸出。 cat 1.作用 cat(“concatenate”的縮寫(xiě))命令用于連接并顯示指定的一個(gè)和多個(gè)文件的有關(guān)信息,它的使用權(quán)限是所有用戶。 2.格式 cat [options] 文件1 文件2…… 3.[options]主要參數(shù) -n:由第一行開(kāi)始對(duì)所有輸出的行數(shù)編號(hào)。 -b:和-n相似,只不過(guò)對(duì)于空白行不編號(hào)。 -s:當(dāng)遇到有連續(xù)兩行以上的空白行時(shí),就代換為一行的空白行。 4.應(yīng)用舉例 (1)cat命令一個(gè)最簡(jiǎn)單的用處是顯示文本文件的內(nèi)容。例如,我們想在命令行看一下README文件的內(nèi)容,可以使用命令: $ cat README (2)有時(shí)需要將幾個(gè)文件處理成一個(gè)文件,并將這種處理的結(jié)果保存到一個(gè)單獨(dú)的輸出文件。cat命令在其輸入上接受一個(gè)或多個(gè)文件,并將它們作為一個(gè)單獨(dú)的文件打印到它的輸出。例如,把README和INSTALL的文件內(nèi)容加上行號(hào)(空白行不加)之后,將內(nèi)容附加到一個(gè)新文本文件File1 中: $ cat README INSTALL File1 (3)cat 還有一個(gè)重要的功能就是可以對(duì)行進(jìn)行編號(hào)。這種功能對(duì)于程序文檔的編制,以及法律和科學(xué)文檔的編制很方便,打印在左邊的行號(hào)使得參考文檔的某一部分變得容易,這些在編程、科學(xué)研究、業(yè)務(wù)報(bào)告甚至是立法工作中都是非常重要的。對(duì)行進(jìn)行編號(hào)功能有-b(只能對(duì)非空白行進(jìn)行編號(hào))和-n(可以對(duì)所有行進(jìn)行編號(hào))兩個(gè)參數(shù): $ cat -b /etc/named.conf ln 1.作用 ln命令用來(lái)在文件之間創(chuàng)建鏈接,它的使用權(quán)限是所有用戶。 2.格式 ln [options] 源文件 [鏈接名] 3.參數(shù) -f:鏈結(jié)時(shí)先將源文件刪除。 -d:允許系統(tǒng)管理者硬鏈結(jié)自己的目錄。 -s:進(jìn)行軟鏈結(jié)(Symbolic Link)。 -b:將在鏈結(jié)時(shí)會(huì)被覆蓋或刪除的文件進(jìn)行備份。 鏈接有兩種,一種被稱為硬鏈接(Hard Link),另一種被稱為符號(hào)鏈接(Symbolic Link)。默認(rèn)情況下,ln命令產(chǎn)生硬鏈接。硬連接指通過(guò)索引節(jié)點(diǎn)來(lái)進(jìn)行的連接。在Linux的文件系統(tǒng)中,保存在磁盤(pán)分區(qū)中的文件不管是什么類型都給它分配一個(gè)編號(hào),稱為索引節(jié)點(diǎn)號(hào)(InodeIndex)。在Linux中,多個(gè)文件名指向同一索引節(jié)點(diǎn)是存在的。一般這種連接就是硬連接。硬連接的作用是允許一個(gè)文件擁有多個(gè)有效路徑名,這樣用戶就可以建立硬連接到重要文件,以防止“誤刪”的功能。其原因如上所述,因?yàn)閷?duì)應(yīng)該目錄的索引節(jié)點(diǎn)有一個(gè)以上的連接。只刪除一個(gè)連接并不影響索引節(jié)點(diǎn)本身和其它的連接,只有當(dāng)最后一個(gè)連接被刪除后,文件的數(shù)據(jù)塊及目錄的連接才會(huì)被釋放。也就是說(shuō),文件才會(huì)被真正刪除。與硬連接相對(duì)應(yīng),Lnux系統(tǒng)中還存在另一種連接,稱為符號(hào)連接(Symbilc Link),也叫軟連接。軟鏈接文件有點(diǎn)類似于Windows的快捷方式。它實(shí)際上是特殊文件的一種。在符號(hào)連接中,文件實(shí)際上是一個(gè)文本文件,其中包含的有另一文件的位置信息。 -------------------------------------------------------------------------------- 作者: ☆-☆ 時(shí)間: 2010-6-8 11:55 本帖最后由 ☆-☆ 于 2010-6-8 11:59 編輯 Android系統(tǒng)在超級(jí)終端下必會(huì)的命令大全(五) 系統(tǒng)管理命令 df 1.作用 df命令用來(lái)檢查文件系統(tǒng)的磁盤(pán)空間占用情況,使用權(quán)限是所有用戶。 2.格式 df [options] 3.主要參數(shù) -s:對(duì)每個(gè)Names參數(shù)只給出占用的數(shù)據(jù)塊總數(shù)。 -a:遞歸地顯示指定目錄中各文件及子目錄中各文件占用的數(shù)據(jù)塊數(shù)。若既不指定-s,也不指定-a,則只顯示Names中的每一個(gè)目錄及其中的各子目錄所占的磁盤(pán)塊數(shù)。 -k:以1024字節(jié)為單位列出磁盤(pán)空間使用情況。 -x:跳過(guò)在不同文件系統(tǒng)上的目錄不予統(tǒng)計(jì)。 -l:計(jì)算所有的文件大小,對(duì)硬鏈接文件則計(jì)算多次。 -i:顯示inode信息而非塊使用量。 -h(huán):以容易理解的格式印出文件系統(tǒng)大小,例如136KB、254MB、21GB。 -P:使用POSIX輸出格式。 -T:顯示文件系統(tǒng)類型。 4.說(shuō)明 df 命令被廣泛地用來(lái)生成文件系統(tǒng)的使用統(tǒng)計(jì)數(shù)據(jù),它能顯示系統(tǒng)中所有的文件系統(tǒng)的信息,包括總?cè)萘?、可用的空閑空間、目前的安裝點(diǎn)等。超級(jí)權(quán)限用戶使用df 命令時(shí)會(huì)發(fā)現(xiàn)這樣的情況:某個(gè)分區(qū)的容量超過(guò)了100%。這是因?yàn)長(zhǎng)inux系統(tǒng)為超級(jí)用戶保留了10%的空間,由其單獨(dú)支配。也就是說(shuō),對(duì)于超級(jí)用戶而言,他所見(jiàn)到的硬盤(pán)容量將是110%。這樣的安排對(duì)于系統(tǒng)管理而言是有好處的,當(dāng)硬盤(pán)被使用的容量接近100%時(shí)系統(tǒng)管理員還可以正常工作。 5.應(yīng)用實(shí)例 Linux支持的文件系統(tǒng)非常多,包括JFS、ReiserFS、ext、ext2、ext3、ISO9660、XFS、Minx、vfat、MSDOS等。使用df -T命令查看磁盤(pán)空間時(shí)還可以得到文件系統(tǒng)的信息: #df -T 文件系統(tǒng) 類型 容量 已用 可用 已用% 掛載點(diǎn) /dev/hda7 reiserfs 5.2G 1.6G 3.7G 30% / /dev/hda1 vfat 2.4G 1.6G 827M 66% /windows/C /dev/hda5 vfat 3.0G 1.7G 1.3G 57% /windows/D /dev/hda9 vfat 3.0G 2.4G 566M 82% /windows/E /dev/hda10 NTFS 3.2G 573M 2.6G 18% /windows/F /dev/hda11 vfat 1.6G 1.5G 23M 99% /windows/G 從上面除了可以看到磁盤(pán)空間的容量、使用情況外,分區(qū)的文件系統(tǒng)類型、掛載點(diǎn)等信息也一覽無(wú)遺。 top 1.作用 top命令用來(lái)顯示執(zhí)行中的程序進(jìn)程,使用權(quán)限是所有用戶。 2.格式 top [-] [d delay] [q] [c] [S] [n] 3.主要參數(shù) d:指定更新的間隔,以秒計(jì)算。 q:沒(méi)有任何延遲的更新。如果使用者有超級(jí)用戶,則top命令將會(huì)以最高的優(yōu)先序執(zhí)行。 c:顯示進(jìn)程完整的路徑與名稱。 S:累積模式,會(huì)將己完成或消失的子行程的CPU時(shí)間累積起來(lái)。 s:安全模式。 i:不顯示任何閑置(Idle)或無(wú)用(Zombie)的行程。 n:顯示更新的次數(shù),完成后將會(huì)退出top。 4.說(shuō)明 top命令是Linux系統(tǒng)管理的一個(gè)主要命令,通過(guò)它可以獲得許多信息。 下面列出了詳細(xì)解釋。 PID(Process ID):進(jìn)程標(biāo)示號(hào)。 USER:進(jìn)程所有者的用戶名。 PR:進(jìn)程的優(yōu)先級(jí)別。 NI:進(jìn)程的優(yōu)先級(jí)別數(shù)值。 VIRT:進(jìn)程占用的虛擬內(nèi)存值。 RES:進(jìn)程占用的物理內(nèi)存值。 SHR:進(jìn)程使用的共享內(nèi)存值。 S:進(jìn)程的狀態(tài),其中S表示休眠,R表示正在運(yùn)行,Z表示僵死狀態(tài),N表示該進(jìn)程優(yōu)先值是負(fù)數(shù)。 %CPU:該進(jìn)程占用的CPU使用率。 %MEM:該進(jìn)程占用的物理內(nèi)存和總內(nèi)存的百分比。 TIME+:該進(jìn)程啟動(dòng)后占用的總的CPU時(shí)間。 Command:進(jìn)程啟動(dòng)的啟動(dòng)命令名稱,如果這一行顯示不下,進(jìn)程會(huì)有一個(gè)完整的命令行。 top命令使用過(guò)程中,還可以使用一些交互的命令來(lái)完成其它參數(shù)的功能。這些命令是通過(guò)快捷鍵啟動(dòng)的。 :立刻刷新。 P:根據(jù)CPU使用大小進(jìn)行排序。 T:根據(jù)時(shí)間、累計(jì)時(shí)間排序。 q:退出top命令。 m:切換顯示內(nèi)存信息。 t:切換顯示進(jìn)程和CPU狀態(tài)信息。 c:切換顯示命令名稱和完整命令行。 M:根據(jù)使用內(nèi)存大小進(jìn)行排序。 W:將當(dāng)前設(shè)置寫(xiě)入~/.toprc文件中。這是寫(xiě)top配置文件的推薦方法。 可以看到,top命令是一個(gè)功能十分強(qiáng)大的監(jiān)控系統(tǒng)的工具,對(duì)于系統(tǒng)管理員而言尤其重要。但是,它的缺點(diǎn)是會(huì)消耗很多系統(tǒng)資源。 free 1.作用 free命令用來(lái)顯示內(nèi)存的使用情況,使用權(quán)限是所有用戶。 2.格式 free [-b|-k|-m] [-o] [-s delay] [-t] [-V] 3.主要參數(shù) -b -k -m:分別以字節(jié)(KB、MB)為單位顯示內(nèi)存使用情況。 -s delay:顯示每隔多少秒數(shù)來(lái)顯示一次內(nèi)存使用情況。 -t:顯示內(nèi)存總和列。 -o:不顯示緩沖區(qū)調(diào)節(jié)列。 4.應(yīng)用實(shí)例 free命令是用來(lái)查看內(nèi)存使用情況的主要命令。和top命令相比,它的優(yōu)點(diǎn)是使用簡(jiǎn)單,并且只占用很少的系統(tǒng)資源。通過(guò)-S參數(shù)可以使用free命令不間斷地監(jiān)視有多少內(nèi)存在使用,這樣可以把它當(dāng)作一個(gè)方便實(shí)時(shí)監(jiān)控器。 #free -b -s5 使用這個(gè)命令后終端會(huì)連續(xù)不斷地報(bào)告內(nèi)存使用情況(以字節(jié)為單位),每5秒更新一次。 chown 1.作用 更改一個(gè)或多個(gè)文件或目錄的屬主和屬組。使用權(quán)限是超級(jí)用戶。 2.格式 chown [選項(xiàng)] 用戶或組 文件 3.主要參數(shù) --dereference:受影響的是符號(hào)鏈接所指示的對(duì)象,而非符號(hào)鏈接本身。 -h, --no-dereference:會(huì)影響符號(hào)鏈接本身,而非符號(hào)鏈接所指示的目的地(當(dāng)系統(tǒng)支持更改符號(hào)鏈接的所有者,此選項(xiàng)才有效)。 --from=目前所有者:目前組只當(dāng)每個(gè)文件的所有者和組符合選項(xiàng)所指定的,才會(huì)更改所有者和組。其中一個(gè)可以省略,這已省略的屬性就不需要符合原有的屬性。 -f, --silent, --quiet:去除大部分的錯(cuò)誤信息。 -R, --recursive:遞歸處理所有的文件及子目錄。 -v, --verbose:處理任何文件都會(huì)顯示信息。 4.說(shuō)明 chown 將指定文件的擁有者改為指定的用戶或組,用戶可以是用戶名或用戶ID;組可以是組名或組ID;文件是以空格分開(kāi)的要改變權(quán)限的文件列表,支持通配符。系統(tǒng)管理員經(jīng)常使用chown命令,在將文件拷貝到另一個(gè)用戶的目錄下以后,讓用戶擁有使用該文件的權(quán)限。 5.應(yīng)用實(shí)例 1.把文件shiyan.c的所有者改為wan $ chown wan shiyan.c 2.把目錄/hi及其下的所有文件和子目錄的屬主改成wan,屬組改成users。 $ chown - R wan.users /hi chattr 1.作用 修改ext2和ext3文件系統(tǒng)屬性(attribute),使用權(quán)限超級(jí)用戶。 2.格式 chattr [-RV] [-+=AacDdijsSu] [-v version] 文件或目錄 3.主要參數(shù) -R:遞歸處理所有的文件及子目錄。 -V:詳細(xì)顯示修改內(nèi)容,并打印輸出。 -:失效屬性。 +:激活屬性。 = :指定屬性。 A:Atime,告訴系統(tǒng)不要修改對(duì)這個(gè)文件的最后訪問(wèn)時(shí)間。 S:Sync,一旦應(yīng)用程序?qū)@個(gè)文件執(zhí)行了寫(xiě)操作,使系統(tǒng)立刻把修改的結(jié)果寫(xiě)到磁盤(pán)。 a:Append Only,系統(tǒng)只允許在這個(gè)文件之后追加數(shù)據(jù),不允許任何進(jìn)程覆蓋或截?cái)噙@個(gè)文件。如果目錄具有這個(gè)屬性,系統(tǒng)將只允許在這個(gè)目錄下建立和修改文件,而不允許刪除任何文件。 i:Immutable,系統(tǒng)不允許對(duì)這個(gè)文件進(jìn)行任何的修改。如果目錄具有這個(gè)屬性,那么任何的進(jìn)程只能修改目錄之下的文件,不允許建立和刪除文件。 D:檢查壓縮文件中的錯(cuò)誤。 d:No dump,在進(jìn)行文件系統(tǒng)備份時(shí),dump程序?qū)⒑雎赃@個(gè)文件。 C:Compress,系統(tǒng)以透明的方式壓縮這個(gè)文件。從這個(gè)文件讀取時(shí),返回的是解壓之后的數(shù)據(jù);而向這個(gè)文件中寫(xiě)入數(shù)據(jù)時(shí),數(shù)據(jù)首先被壓縮之后才寫(xiě)入磁盤(pán)。 s:Secure Delete,讓系統(tǒng)在刪除這個(gè)文件時(shí),使用0填充文件所在的區(qū)域。 u:Undelete,當(dāng)一個(gè)應(yīng)用程序請(qǐng)求刪除這個(gè)文件,系統(tǒng)會(huì)保留其數(shù)據(jù)塊以便以后能夠恢復(fù)刪除這個(gè)文件。 4.說(shuō)明 chattr 命令的作用很大,其中一些功能是由Linux內(nèi)核版本來(lái)支持的,如果Linux內(nèi)核版本低于2.2,那么許多功能不能實(shí)現(xiàn)。同樣-D檢查壓縮文件中的錯(cuò)誤 的功能,需要2.5.19以上內(nèi)核才能支持。另外,通過(guò)chattr命令修改屬性能夠提高系統(tǒng)的安全性,但是它并不適合所有的目錄。chattr命令不能 保護(hù)/、/dev、/tmp、/var目錄。 5.應(yīng)用實(shí)例 1.恢復(fù)/root目錄,即子目錄的所有文件 # chattr -R +u/root 2.用chattr命令防止系統(tǒng)中某個(gè)關(guān)鍵文件被修改 在Linux下,有些配置文件(passwd ,fatab)是不允許任何人修改的,為了防止被誤刪除或修改,可以設(shè)定該文件的“不可修改位(immutable)”,命令如下: # chattr +i /etc/fstab ps 1.作用 ps顯示瞬間進(jìn)程 (process) 的動(dòng)態(tài),使用權(quán)限是所有使用者。 2.格式 ps [options] [--help] 3.主要參數(shù) ps的參數(shù)非常多, 此出僅列出幾個(gè)常用的參數(shù)。 -A:列出所有的進(jìn)程。 -l:顯示長(zhǎng)列表。 -m:顯示內(nèi)存信息。 -w:顯示加寬可以顯示較多的信息。 -e:顯示所有進(jìn)程。 a:顯示終端上的所有進(jìn)程,包括其它用戶的進(jìn)程。 -au:顯示較詳細(xì)的信息。 -aux:顯示所有包含其它使用者的進(jìn)程。 4.說(shuō)明 要 對(duì)進(jìn)程進(jìn)行監(jiān)測(cè)和控制,首先要了解當(dāng)前進(jìn)程的情況,也就是需要查看當(dāng)前進(jìn)程。ps命令就是最基本、也是非常強(qiáng)大的進(jìn)程查看命令。使用該命令可以確定有哪些 進(jìn)程正在運(yùn)行、運(yùn)行的狀態(tài)、進(jìn)程是否結(jié)束、進(jìn)程有沒(méi)有僵尸、哪些進(jìn)程占用了過(guò)多的資源等。圖2給出了ps-aux命令詳解。大部分信息都可以通過(guò)執(zhí)行該命 令得到。最常用的三個(gè)參數(shù)是u、a、x。下面就結(jié)合這三個(gè)參數(shù)詳細(xì)說(shuō)明ps命令的作用:ps aux 圖2 ps-aux命令詳解 圖2第2行代碼中,USER表示進(jìn)程擁有者;PID表示進(jìn)程標(biāo)示符;%CPU表示占用的CPU使用率;%MEM占用的物理內(nèi)存使用率;VSZ表示占用的虛擬內(nèi)存大?。籖SS為進(jìn)程占用的物理內(nèi)存值;TTY為終端的次要裝置號(hào)碼。 STAT 表示進(jìn)程的狀態(tài),其中D為不可中斷的靜止(I/O動(dòng)作);R正在執(zhí)行中;S靜止?fàn)顟B(tài);T暫停執(zhí)行;Z不存在,但暫時(shí)無(wú)法消除;W沒(méi)有足夠的內(nèi)存分頁(yè)可分 配;高優(yōu)先序的進(jìn)程;N低優(yōu)先序的進(jìn)程;L有內(nèi)存分頁(yè)分配并鎖在內(nèi)存體內(nèi) (實(shí)時(shí)系統(tǒng)或 I/O)。START為進(jìn)程開(kāi)始時(shí)間。TIME為執(zhí)行的時(shí)間。COMMAND是所執(zhí)行的指令。 4.應(yīng)用實(shí)例 在進(jìn)行系統(tǒng)維護(hù)時(shí),經(jīng)常會(huì)出現(xiàn)內(nèi)存使用量驚人,而又不知道是哪一個(gè)進(jìn)程占用了大量進(jìn)程的情況。除了可以使用top命令查看內(nèi)存使用情況之外,還可以使用下面的命令: ps aux | sort +5n -------------------------------------------------------------------------------- 作者: ☆-☆ 時(shí)間: 2010-6-8 11:58 Android系統(tǒng)在超級(jí)終端下必會(huì)的命令大全(十) 六、其他命令 tar 1.作用 tar命令是Unix/Linux系統(tǒng)中備份文件的可靠方法,幾乎可以工作于任何環(huán)境中,它的使用權(quán)限是所有用戶。 2.格式 tar [主選項(xiàng)+輔選項(xiàng)] 文件或目錄 3.主要參數(shù) 使用該命令時(shí),主選項(xiàng)是必須要有的,它告訴tar要做什么事情,輔選項(xiàng)是輔助使用的,可以選用。 主選項(xiàng): -c 創(chuàng)建新的檔案文件。如果用戶想備份一個(gè)目錄或是一些文件,就要選擇這個(gè)選項(xiàng)。 -r 把要存檔的文件追加到檔案文件的未尾。例如用戶已經(jīng)做好備份文件,又發(fā)現(xiàn)還有一個(gè)目錄或是一些文件忘記備份了,這時(shí)可以使用該選項(xiàng),將忘記的目錄或文件追加到備份文件中。 -t 列出檔案文件的內(nèi)容,查看已經(jīng)備份了哪些文件。 -u 更新文件。就是說(shuō),用新增的文件取代原備份文件,如果在備份文件中找不到要更新的文件,則把它追加到備份文件的最后。 -x 從檔案文件中釋放文件。 輔助選項(xiàng): -b 該選項(xiàng)是為磁帶機(jī)設(shè)定的,其后跟一數(shù)字,用來(lái)說(shuō)明區(qū)塊的大小,系統(tǒng)預(yù)設(shè)值為20(20?512 bytes)。 -f 使用檔案文件或設(shè)備,這個(gè)選項(xiàng)通常是必選的。 -k 保存已經(jīng)存在的文件。例如把某個(gè)文件還原,在還原的過(guò)程中遇到相同的文件,不會(huì)進(jìn)行覆蓋。 -m 在還原文件時(shí),把所有文件的修改時(shí)間設(shè)定為現(xiàn)在。 -M 創(chuàng)建多卷的檔案文件,以便在幾個(gè)磁盤(pán)中存放。 -v 詳細(xì)報(bào)告tar處理的文件信息。如無(wú)此選項(xiàng),tar不報(bào)告文件信息。 -w 每一步都要求確認(rèn)。 -z 用gzip來(lái)壓縮/解壓縮文件,加上該選項(xiàng)后可以將檔案文件進(jìn)行壓縮,但還原時(shí)也一定要使用該選項(xiàng)進(jìn)行解壓縮。 4.應(yīng)用說(shuō)明 tar 是Tape Archive(磁帶歸檔)的縮寫(xiě),最初設(shè)計(jì)用于將文件打包到磁帶上。如果下載過(guò)Linux的源代碼,或許已經(jīng)碰到過(guò)tar文件 請(qǐng)注意,不要忘了Linux是區(qū)分大小寫(xiě)的。例如,tar命令應(yīng)該總是以小寫(xiě)的形式執(zhí)行。命令行開(kāi)關(guān)可以是大寫(xiě)、小寫(xiě)或大小寫(xiě)的混合。例如,-t和-T執(zhí)行不同的功能。文件或目錄名稱可以混合使用大小寫(xiě),而且就像命令和命令行開(kāi)關(guān)一樣是區(qū)分大小寫(xiě)的。 5.應(yīng)用實(shí)例 tar是一個(gè)命令行的工具,沒(méi)有圖形界面。使用Konsole打開(kāi)一個(gè)終端窗口,接下來(lái)是一個(gè)簡(jiǎn)單的備份命令(在/temp目錄中創(chuàng)建一個(gè)back.tar的文件,/usr目錄中所有內(nèi)容都包含在其中。): $tar cvf - /usr > /temp/back.tar 另 外,tar命令支持前面第三講中講過(guò)的crontab命令,可以用crontab工具設(shè)置成基于時(shí)間的有規(guī)律地運(yùn)行。例如,每晚6點(diǎn)把/usr目錄備份到 hda—第一個(gè)IDE接口的主驅(qū)動(dòng)器 (總是位于第一個(gè)硬盤(pán))中,只要將下面語(yǔ)句添加到root的crontab中即可: $00 06 * * * tar cvf /dev/hda1/usrfiles.tar - /usr 一般情況下,以下這些目錄是需要備份的: ◆/etc 包含所有核心配置文件,其中包括網(wǎng)絡(luò)配置、系統(tǒng)名稱、防火墻規(guī)則、用戶、組,以及其它全局系統(tǒng)項(xiàng)。 ◆ /var 包含系統(tǒng)守護(hù)進(jìn)程(服務(wù))所使用的信息,包括DNS配置、DHCP租期、郵件緩沖文件、HTTP服務(wù)器文件、dB2實(shí)例配置等。 ◆/home 包含所有默認(rèn)用戶的主目錄,包括個(gè)人設(shè)置、已下載的文件和用戶不希望失去的其它信息。 ◆/root 根(root)用戶的主目錄。 ◆/opt 是安裝許多非系統(tǒng)文件的地方。IBM軟件就安裝在這里。OpenOffice、JDK和其它軟件在默認(rèn)情況下也安裝在這里。 有些目錄是可以不備份的: ◆ /proc 應(yīng)該永遠(yuǎn)不要備份這個(gè)目錄。它不是一個(gè)真實(shí)的文件系統(tǒng),而是運(yùn)行內(nèi)核和環(huán)境的虛擬化視圖,包括諸如/proc/kcore這樣的文件,這個(gè)文件是整個(gè)運(yùn)行內(nèi)存的虛擬視圖。備份這些文件只是在浪費(fèi)資源。 ◆/dev 包含硬件設(shè)備的文件表示。如果計(jì)劃還原到一個(gè)空白的系統(tǒng),就可以備份/dev。然而,如果計(jì)劃還原到一個(gè)已安裝的Linux 系統(tǒng),那么備份/dev是沒(méi)有必要的。 unzip 1.作用 unzip 命令位于/usr/bin目錄中,它們和MS DOS下的pkzip、pkunzip及MS Windows中的Winzip軟件功能一樣,將文件壓縮成.zip文件,以節(jié)省硬盤(pán)空間,當(dāng)需要的時(shí)候再將壓縮文件用unzip命令解開(kāi)。該命令使用權(quán) 限是所有用戶。 2.格式 unzip [-cflptuvz][-agCjLMnoqsVX][-P ][.zip文件][文件][-d ][-x ] 3.主要參數(shù) -c:將解壓縮的結(jié)果顯示到屏幕上,并對(duì)字符做適當(dāng)?shù)霓D(zhuǎn)換。 -f:更新現(xiàn)有的文件。 -l:顯示壓縮文件內(nèi)所包含的文件。 -p:與-c參數(shù)類似,會(huì)將解壓縮的結(jié)果顯示到屏幕上,但不會(huì)執(zhí)行任何的轉(zhuǎn)換。 -t:檢查壓縮文件是否正確。 -u:與-f參數(shù)類似,但是除了更新現(xiàn)有的文件外,也會(huì)將壓縮文件中的其它文件解壓縮到目錄中。 -v:執(zhí)行是時(shí)顯示詳細(xì)的信息。 -z:僅顯示壓縮文件的備注文字。 -a:對(duì)文本文件進(jìn)行必要的字符轉(zhuǎn)換。 -b:不要對(duì)文本文件進(jìn)行字符轉(zhuǎn)換。 -C:壓縮文件中的文件名稱區(qū)分大小寫(xiě)。 -j:不處理壓縮文件中原有的目錄路徑。 -L:將壓縮文件中的全部文件名改為小寫(xiě)。 -M:將輸出結(jié)果送到more程序處理。 -n:解壓縮時(shí)不要覆蓋原有的文件。 -o:不必先詢問(wèn)用戶,unzip執(zhí)行后覆蓋原有文件。 -P:使用zip的密碼選項(xiàng)。 -q:執(zhí)行時(shí)不顯示任何信息。 -s:將文件名中的空白字符轉(zhuǎn)換為底線字符。 -V:保留VMS的文件版本信息。 -X:解壓縮時(shí)同時(shí)回存文件原來(lái)的UID/GID。 [.zip文件]:指定.zip壓縮文件。 [文件]:指定要處理.zip壓縮文件中的哪些文件。 -d:指定文件解壓縮后所要存儲(chǔ)的目錄。 -x:指定不要處理.zip壓縮文件中的哪些文件。 -Z unzip:-Z等于執(zhí)行zipinfo指令。在Linux中,還提供了一個(gè)叫zipinfo的工具,能夠察看zip壓縮文件的詳細(xì)信息。 gunzip 1.作用 gunzip命令作用是解壓文件,使用權(quán)限是所有用戶。 2.格式 gunzip [-acfhlLnNqrtvV][-s ][文件...] 或者 gunzip [-acfhlLnNqrtvV][-s ][目錄](méi) 3.主要參數(shù) -a或--ascii:使用ASCII文字模式。 -c或--stdout或--to-stdout:把解壓后的文件輸出到標(biāo)準(zhǔn)輸出設(shè)備。 -f或-force:強(qiáng)行解開(kāi)壓縮文件,不理會(huì)文件名稱或硬連接是否存在,以及該文件是否為符號(hào)連接。 -h或--help:在線幫助。 -l或--list:列出壓縮文件的相關(guān)信息。 -L或--license:顯示版本與版權(quán)信息。 -n或--no-name:解壓縮時(shí),若壓縮文件內(nèi)含有原來(lái)的文件名稱及時(shí)間戳記,則將其忽略不予處理。 -N或--name:解壓縮時(shí),若壓縮文件內(nèi)含有原來(lái)的文件名稱及時(shí)間戳記,則將其回存到解開(kāi)的文件上。 -q或--quiet:不顯示警告信息。 -r或--recursive:遞歸處理,將指定目錄下的所有文件及子目錄一并處理。 -S或--suffix:更改壓縮字尾字符串。 -t或--test:測(cè)試壓縮文件是否正確無(wú)誤。 -v或--verbose:顯示指令執(zhí)行過(guò)程。 -V或--version:顯示版本信息。 4.說(shuō)明 gunzip是個(gè)使用廣泛的解壓縮程序,它用于解開(kāi)被gzip壓縮過(guò)的文件,這些壓縮文件預(yù)設(shè)最后的擴(kuò)展名為“.gz”。事實(shí)上,gunzip就是gzip的硬連接,因此不論是壓縮或解壓縮,都可通過(guò)gzip指令單獨(dú)完成。gunzip最新版本是1.3.3 。 
 那就首先說(shuō)點(diǎn)Runtime類吧,他是一個(gè)與JVM運(yùn)行時(shí)環(huán)境有關(guān)的類,這個(gè)類是Singleton的。我說(shuō)幾個(gè)自己覺(jué)得重要的地方。 1、Runtime.getRuntime()可以取得當(dāng)前JVM的運(yùn)行時(shí)環(huán)境,這也是在Java中唯一一個(gè)得到運(yùn)行時(shí)環(huán)境的方法。 2、Runtime上其他大部分的方法都是實(shí)例方法,也就是說(shuō)每次進(jìn)行運(yùn)行時(shí)調(diào)用時(shí)都要用到getRuntime方法。 3、 Runtime中的exit方法是退出當(dāng)前JVM的方法,估計(jì)也是唯一的一個(gè)吧,因?yàn)槲铱吹絊ystem類中的exit實(shí)際上也是通過(guò)調(diào)用 Runtime.exit()來(lái)退出JVM的,這里說(shuō)明一下Java對(duì)Runtime返回值的一般規(guī)則(后邊也提到了),0代表正常退出,非0代表異常中止,這只是Java的規(guī)則,在各個(gè)操作系統(tǒng)中總會(huì)發(fā)生一些小的混淆。 4、Runtime.addShutdownHook()方法可以注冊(cè)一個(gè)hook在JVM執(zhí)行shutdown的過(guò)程中,方法的參數(shù)只要是一個(gè)初始化過(guò)但是沒(méi)有執(zhí)行的Thread實(shí)例就可以。(注意,Java中的Thread都是執(zhí)行過(guò)了就不值錢(qián)的哦) 5、說(shuō)到addShutdownHook這個(gè)方法就要說(shuō)一下JVM運(yùn)行環(huán)境是在什么情況下shutdown或者abort的。文檔上是這樣寫(xiě)的,當(dāng)最后一個(gè)非精靈進(jìn)程退出或者收到了一個(gè)用戶中斷信號(hào)、用戶登出、系統(tǒng)shutdown、Runtime的exit方法被調(diào)用時(shí)JVM會(huì)啟動(dòng)shutdown的過(guò)程,在這個(gè)過(guò)程開(kāi)始后,他會(huì)并行啟動(dòng)所有登記的shutdown hook(注意是并行啟動(dòng),這就需要線程安全和防止死鎖)。當(dāng)shutdown過(guò)程啟動(dòng)后,只有通過(guò)調(diào)用halt方法才能中止shutdown的過(guò)程并退出JVM。 那什么時(shí)候JVM會(huì)abort退出那?首先說(shuō)明一下,abort退出時(shí)JVM就是停止運(yùn)行但并不一定進(jìn)行shutdown。這只有JVM在遇到SIGKILL信號(hào)或者windows中止進(jìn)程的信號(hào)、本地方法發(fā)生類似于訪問(wèn)非法地址一類的內(nèi)部錯(cuò)誤時(shí)會(huì)出現(xiàn)。這種情況下并不能保證shutdown hook是否被執(zhí)行。 現(xiàn)在開(kāi)始看這篇文章,呵呵。 首先講的是Runtime.exec()方法的所有重載。這里要注意的有一點(diǎn),就是public Process exec(String [] cmdArray, String [] envp);這個(gè)方法中cmdArray是一個(gè)執(zhí)行的命令和參數(shù)的字符串?dāng)?shù)組,數(shù)組的第一個(gè)元素是要執(zhí)行的命令往后依次都是命令的參數(shù),envp我個(gè)人感覺(jué)應(yīng)該和C中的execve中的環(huán)境變量是一樣的,envp中使用的是name=value的方式。 <!--[if !supportLists]-->1、 <!--[endif]-->一個(gè)很糟糕的調(diào)用程序,代碼如下,這個(gè)程序用exec調(diào)用了一個(gè)外部命令之后馬上使用exitValue就對(duì)其返回值進(jìn)行檢查,讓我們看看會(huì)出現(xiàn)什么問(wèn)題。 import java.util.*; import java.io.*; public class BadExecJavac { public static void main(String args[]) { try { Runtime rt = Runtime.getRuntime(); Process proc = rt.exec("javac"); int exitVal = proc.exitValue(); System.out.println("Process exitValue: " + exitVal); } catch (Throwable t) { t.printStackTrace(); } } } A run of BadExecJavac produces: E:classescomjavaworldjpitfallsarticle2>java BadExecJavac java.lang.IllegalThreadStateException: process has not exited at java.lang.Win32Process.exitValue(Native Method) at BadExecJavac.main(BadExecJavac.java:13) 這里看原文就可以了解,這里主要的問(wèn)題就是錯(cuò)誤的調(diào)用了exitValue來(lái)取得外部命令的返回值(呵呵,這個(gè)錯(cuò)誤我也曾經(jīng)犯過(guò)),因?yàn)閑xitValue 這個(gè)方法是不阻塞的,程序在調(diào)用這個(gè)方法時(shí)外部命令并沒(méi)有返回所以造成了異常的出現(xiàn),這里是由另外的方法來(lái)等待外部命令執(zhí)行完畢的,就是waitFor方法,這個(gè)方法會(huì)一直阻塞直到外部命令執(zhí)行結(jié)束,然后返回外部命令執(zhí)行的結(jié)果,作者在這里一頓批評(píng)設(shè)計(jì)者的思路有問(wèn)題,呵呵,反正我是無(wú)所謂阿,能用就可以拉。但是作者在這里有一個(gè)說(shuō)明,就是exitValue也是有好多用途的。因?yàn)楫?dāng)你在一個(gè)Process上調(diào)用waitFor方法時(shí),當(dāng)前線程是阻塞的,如果外部命令無(wú)法執(zhí)行結(jié)束,那么你的線程就會(huì)一直阻塞下去,這種意外會(huì)影響我們程序的執(zhí)行。所以在我們不能判斷外部命令什么時(shí)候執(zhí)行完畢而我們的程序還需要繼續(xù)執(zhí)行的情況下,我們就應(yīng)該循環(huán)的使用exitValue來(lái)取得外部命令的返回狀態(tài),并在外部命令返回時(shí)作出相應(yīng)的處理。 2、對(duì)exitValue處改進(jìn)了的程序 import java.util.*; import java.io.*; public class BadExecJavac2 { public static void main(String args[]) { try { Runtime rt = Runtime.getRuntime(); Process proc = rt.exec("javac"); int exitVal = proc.waitFor(); System.out.println("Process exitValue: " + exitVal); } catch (Throwable t) { t.printStackTrace(); } } } 不幸的是,這個(gè)程序也無(wú)法執(zhí)行完成,它沒(méi)有輸出但卻一直懸在那里,這是為什么那? JDK文檔中對(duì)此有如此的解釋:因?yàn)楸镜氐南到y(tǒng)對(duì)標(biāo)準(zhǔn)輸入和輸出所提供的緩沖池有效,所以錯(cuò)誤的對(duì)標(biāo)準(zhǔn)輸出快速的寫(xiě)入和從標(biāo)準(zhǔn)輸入快速的讀入都有可能造成子進(jìn)程的鎖,甚至死鎖。 文檔引述完了,作者又開(kāi)始批評(píng)了,他說(shuō)JDK僅僅說(shuō)明為什么問(wèn)題會(huì)發(fā)生,卻并沒(méi)有說(shuō)明這個(gè)問(wèn)題怎么解決,這的確是個(gè)問(wèn)題哈。緊接著作者說(shuō)出自己的做法,就是在執(zhí)行完外部命令后我們要控制好Process的所有輸入和輸出(視情況而定),在這個(gè)例子里邊因?yàn)檎{(diào)用的是Javac,而他在沒(méi)有參數(shù)的情況下會(huì)將提示信息輸出到標(biāo)準(zhǔn)出錯(cuò),所以在下面的程序中我們要對(duì)此進(jìn)行處理。 import java.util.*; import java.io.*; public class MediocreExecJavac { public static void main(String args[]) { try { Runtime rt = Runtime.getRuntime(); Process proc = rt.exec("javac"); InputStream stderr = proc.getErrorStream(); InputStreamReader isr = new InputStreamReader(stderr); BufferedReader br = new BufferedReader(isr); String line = null; System.out.println("<ERROR>"); while ( (line = br.readLine()) != null) System.out.println(line); System.out.println("</ERROR>"); int exitVal = proc.waitFor(); System.out.println("Process exitValue: " + exitVal); } catch (Throwable t) { t.printStackTrace(); } } } 程序的運(yùn)行結(jié)果為 E:classescomjavaworldjpitfallsarticle2>java MediocreExecJavac <ERROR> Usage: javac <options> <source files> where <options> includes: -g Generate all debugging info -g:none Generate no debugging info -g:{lines,vars,source} Generate only some debugging info -O Optimize; may hinder debugging or enlarge class files -nowarn Generate no warnings -verbose Output messages about what the compiler is doing -deprecation Output source locations where deprecated APIs are used -classpath <path> Specify where to find user class files -sourcepath <path> Specify where to find input source files -bootclasspath <path> Override location of bootstrap class files -extdirs <dirs> Override location of installed extensions -d <directory> Specify where to place generated class files -encoding <encoding> Specify character encoding used by source files -target <release> Generate class files for specific VM version </ERROR> Process exitValue: 2 哎,不管怎么說(shuō)還是出來(lái)了結(jié)果,作者作了一下總結(jié),就是說(shuō),為了處理好外部命令大量輸出的情況,你要確保你的程序處理好外部命令所需要的輸入或者輸出。 下一個(gè)題目,當(dāng)我們調(diào)用一個(gè)我們認(rèn)為是可執(zhí)行程序的時(shí)候容易發(fā)生的錯(cuò)誤(今天晚上我剛剛犯這個(gè)錯(cuò)誤,沒(méi)事做這個(gè)練習(xí)時(shí)候發(fā)生的) import java.util.*; import java.io.*; public class BadExecWinDir { public static void main(String args[]) { try { Runtime rt = Runtime.getRuntime(); Process proc = rt.exec("dir"); InputStream stdin = proc.getInputStream(); InputStreamReader isr = new InputStreamReader(stdin); BufferedReader br = new BufferedReader(isr); String line = null; System.out.println("<OUTPUT>"); while ( (line = br.readLine()) != null) System.out.println(line); System.out.println("</OUTPUT>"); int exitVal = proc.waitFor(); System.out.println("Process exitValue: " + exitVal); } catch (Throwable t) { t.printStackTrace(); } } } A run of BadExecWinDir produces: E:classescomjavaworldjpitfallsarticle2>java BadExecWinDir java.io.IOException: CreateProcess: dir error=2 at java.lang.Win32Process.create(Native Method) at java.lang.Win32Process.<init>(Unknown Source) at java.lang.Runtime.execInternal(Native Method) at java.lang.Runtime.exec(Unknown Source) at java.lang.Runtime.exec(Unknown Source) at java.lang.Runtime.exec(Unknown Source) at java.lang.Runtime.exec(Unknown Source) at BadExecWinDir.main(BadExecWinDir.java:12) 說(shuō)實(shí)在的,這個(gè)錯(cuò)誤還真是讓我摸不著頭腦,我覺(jué)得在windows中返回2應(yīng)該是沒(méi)有找到這個(gè)文件的緣故,可能windows 2000中只有cmd命令,dir命令不是當(dāng)前環(huán)境變量能夠解釋的吧。我也不知道了,慢慢往下看吧。 嘿,果然和作者想的一樣,就是因?yàn)閐ir命令是由windows中的解釋器解釋的,直接執(zhí)行dir時(shí)無(wú)法找到dir.exe這個(gè)命令,所以會(huì)出現(xiàn)文件未找到這個(gè)2的錯(cuò)誤。如果我們要執(zhí)行這樣的命令,就要先根據(jù)操作系統(tǒng)的不同執(zhí)行不同的解釋程序command.com 或者cmd.exe。 作者對(duì)上邊的程序進(jìn)行了修改 import java.util.*; import java.io.*; class StreamGobbler extends Thread { InputStream is; String type; StreamGobbler(InputStream is, String type) { this.is = is; this.type = type; } public void run() { try { InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr); String line=null; while ( (line = br.readLine()) != null) System.out.println(type + ">" + line); } catch (IOException ioe) { ioe.printStackTrace(); } } } public class GoodWindowsExec { public static void main(String args[]) { if (args.length < 1) { System.out.println("USAGE: java GoodWindowsExec <cmd>"); System.exit(1); } try { String osName = System.getProperty("os.name" ); String[] cmd = new String[3]; if( osName.equals( "Windows NT" ) ) { cmd[0] = "cmd.exe" ; cmd[1] = "/C" ; cmd[2] = args[0]; } else if( osName.equals( "Windows 95" ) ) { cmd[0] = "command.com" ; cmd[1] = "/C" ; cmd[2] = args[0]; } Runtime rt = Runtime.getRuntime(); System.out.println("Execing " + cmd[0] + " " + cmd[1] + " " + cmd[2]); Process proc = rt.exec(cmd); // any error message? StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream(), "ERROR"); // any output? StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), "OUTPUT"); // kick them off errorGobbler.start(); outputGobbler.start(); // any error??? int exitVal = proc.waitFor(); System.out.println("ExitValue: " + exitVal); } catch (Throwable t) { t.printStackTrace(); } } } Running GoodWindowsExec with the dir command generates: E:classescomjavaworldjpitfallsarticle2>java GoodWindowsExec "dir *.java" Execing cmd.exe /C dir *.java OUTPUT> Volume in drive E has no label. OUTPUT> Volume Serial Number is 5C5F-0CC9 OUTPUT> OUTPUT> Directory of E:classescomjavaworldjpitfallsarticle2 OUTPUT> OUTPUT>10/23/00 09:01p 805 BadExecBrowser.java OUTPUT>10/22/00 09:35a 770 BadExecBrowser1.java OUTPUT>10/24/00 08:45p 488 BadExecJavac.java OUTPUT>10/24/00 08:46p 519 BadExecJavac2.java OUTPUT>10/24/00 09:13p 930 BadExecWinDir.java OUTPUT>10/22/00 09:21a 2,282 BadURLPost.java OUTPUT>10/22/00 09:20a 2,273 BadURLPost1.java ... (some output omitted for brevity) OUTPUT>10/12/00 09:29p 151 SuperFrame.java OUTPUT>10/24/00 09:23p 1,814 TestExec.java OUTPUT>10/09/00 05:47p 23,543 TestStringReplace.java OUTPUT>10/12/00 08:55p 228 TopLevel.java OUTPUT> 22 File(s) 46,661 bytes OUTPUT> 19,678,420,992 bytes free ExitValue: 0 這里作者教了一個(gè)windows中很有用的方法,呵呵,至少我是不知道的,就是cmd.exe /C +一個(gè)windows中注冊(cè)了后綴的文檔名,windows會(huì)自動(dòng)地調(diào)用相關(guān)的程序來(lái)打開(kāi)這個(gè)文檔,我試了一下,的確很好用,但是好像文件路徑中有空格的話就有點(diǎn)問(wèn)題,我加上引號(hào)也無(wú)法解決。 這里作者強(qiáng)調(diào)了一下,不要假設(shè)你執(zhí)行的程序是可執(zhí)行的程序,要清楚自己的程序是單獨(dú)可執(zhí)行的還是被解釋的,本章的結(jié)束作者會(huì)介紹一個(gè)命令行工具來(lái)幫助我們分析。 這里還有一點(diǎn),就是得到process的輸出的方式是getInputStream,這是因?yàn)槲覀円獜腏ava 程序的角度來(lái)看,外部程序的輸出對(duì)于Java來(lái)說(shuō)就是輸入,反之亦然。 最后的一個(gè)漏洞的地方就是錯(cuò)誤的認(rèn)為exec方法會(huì)接受所有你在命令行或者Shell中輸入并接受的字符串。這些錯(cuò)誤主要出現(xiàn)在命令作為參數(shù)的情況下,程序員錯(cuò)誤的將所有命令行中可以輸入的參數(shù)命令加入到exec中(這段翻譯的不好,湊合看吧)。下面的例子中就是一個(gè)程序員想重定向一個(gè)命令的輸出。 import java.util.*; import java.io.*; // StreamGobbler omitted for brevity public class BadWinRedirect { public static void main(String args[]) { try { Runtime rt = Runtime.getRuntime(); Process proc = rt.exec("java jecho 'Hello World' > test.txt"); // any error message? StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream(), "ERROR"); // any output? StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), "OUTPUT"); // kick them off errorGobbler.start(); outputGobbler.start(); // any error??? int exitVal = proc.waitFor(); System.out.println("ExitValue: " + exitVal); } catch (Throwable t) { t.printStackTrace(); } } } Running BadWinRedirect produces: E:classescomjavaworldjpitfallsarticle2>java BadWinRedirect OUTPUT>'Hello World' > test.txt ExitValue: 0 程序員的本意是將Hello World這個(gè)輸入重訂向到一個(gè)文本文件中,但是這個(gè)文件并沒(méi)有生成,jecho僅僅是將命令行中的參數(shù)輸出到標(biāo)準(zhǔn)輸出中,用戶覺(jué)得可以像dos中重定向一樣將輸出重定向到一個(gè)文件中,但這并不能實(shí)現(xiàn),用戶錯(cuò)誤的將exec認(rèn)為是一個(gè)shell解釋器,但它并不是,如果你想將一個(gè)程序的輸出重定向到其他的程序中,你必須用程序來(lái)實(shí)現(xiàn)他??捎胘ava.io中的包。 import java.util.*; import java.io.*; class StreamGobbler extends Thread { InputStream is; String type; OutputStream os; StreamGobbler(InputStream is, String type) { this(is, type, null); } StreamGobbler(InputStream is, String type, OutputStream redirect) { this.is = is; this.type = type; this.os = redirect; } public void run() { try { PrintWriter pw = null; if (os != null) pw = new PrintWriter(os); InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr); String line=null; while ( (line = br.readLine()) != null) { if (pw != null) pw.println(line); System.out.println(type + ">" + line); } if (pw != null) pw.flush(); } catch (IOException ioe) { ioe.printStackTrace(); } } } public class GoodWinRedirect { public static void main(String args[]) { if (args.length < 1) { System.out.println("USAGE java GoodWinRedirect <outputfile>"); System.exit(1); } try { FileOutputStream fos = new FileOutputStream(args[0]); Runtime rt = Runtime.getRuntime(); Process proc = rt.exec("java jecho 'Hello World'"); // any error message? StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream(), "ERROR"); // any output? StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), "OUTPUT", fos); // kick them off errorGobbler.start(); outputGobbler.start(); // any error??? int exitVal = proc.waitFor(); System.out.println("ExitValue: " + exitVal); fos.flush(); fos.close(); } catch (Throwable t) { t.printStackTrace(); } } } Running GoodWinRedirect produces: E:classescomjavaworldjpitfallsarticle2>java GoodWinRedirect test.txt OUTPUT>'Hello World' ExitValue: 0 這里就不多說(shuō)了,看看就明白,緊接著作者給出了一個(gè)監(jiān)測(cè)命令的小程序 import java.util.*; import java.io.*; // class StreamGobbler omitted for brevity public class TestExec { public static void main(String args[]) { if (args.length < 1) { System.out.println("USAGE: java TestExec "cmd""); System.exit(1); } try { String cmd = args[0]; Runtime rt = Runtime.getRuntime(); Process proc = rt.exec(cmd); // any error message? StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream(), "ERR"); // any output? StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), "OUT"); // kick them off errorGobbler.start(); outputGobbler.start(); // any error??? int exitVal = proc.waitFor(); System.out.println("ExitValue: " + exitVal); } catch (Throwable t) { t.printStackTrace(); } } } 對(duì)這個(gè)程序進(jìn)行運(yùn)行: E:classescomjavaworldjpitfallsarticle2>java TestExec "e:javadocsindex.html" java.io.IOException: CreateProcess: e:javadocsindex.html error=193 at java.lang.Win32Process.create(Native Method) at java.lang.Win32Process.<init>(Unknown Source) at java.lang.Runtime.execInternal(Native Method) at java.lang.Runtime.exec(Unknown Source) at java.lang.Runtime.exec(Unknown Source) at java.lang.Runtime.exec(Unknown Source) at java.lang.Runtime.exec(Unknown Source) at TestExec.main(TestExec.java:45) 193在windows中是說(shuō)這不是一個(gè)win32程序,這說(shuō)明路徑中找不到這個(gè)網(wǎng)頁(yè)的關(guān)聯(lián)程序,下面作者決定用一個(gè)絕對(duì)路徑來(lái)試一下。 E:classescomjavaworldjpitfallsarticle2>java TestExec "e:program filesnetscapeprogramnetscape.exe e:javadocsindex.html" ExitValue: 0 好用了,這個(gè)我也試了一下,用的是IE。 最后,作者總結(jié)了幾條規(guī)則,防止我們?cè)谶M(jìn)行Runtime.exec()調(diào)用時(shí)出現(xiàn)錯(cuò)誤。 <!--[if !supportLists]-->1、 <!--[endif]-->在一個(gè)外部進(jìn)程執(zhí)行完之前你不能得到他的退出狀態(tài) <!--[if !supportLists]-->2、 <!--[endif]-->在你的外部程序開(kāi)始執(zhí)行的時(shí)候你必須馬上控制輸入、輸出、出錯(cuò)這些流。 <!--[if !supportLists]-->3、 <!--[endif]-->你必須用Runtime.exec()去執(zhí)行程序 <!--[if !supportLists]-->4、 <!--[endif]-->你不能象命令行一樣使用Runtime.exec()。 這是一對(duì)繼承于InputStream和OutputStream的類,用于本地文件讀寫(xiě)(二進(jìn)制格式讀寫(xiě)并且是順序讀寫(xiě),讀和寫(xiě)要分別創(chuàng)建出不同的文件流對(duì)象);  本地文件讀寫(xiě)編程的基本過(guò)程為: ① 生成文件流對(duì)象(對(duì)文件讀操作時(shí)應(yīng)該為FileInputStream類,而文件寫(xiě)應(yīng)該為FileOutputStream類); ② 調(diào)用FileInputStream或FileOutputStream類中的功能函數(shù)如read()、write(int b)等)讀寫(xiě)文件內(nèi)容; ③ 關(guān)閉文件(close())。 實(shí)例:流文件讀寫(xiě) 流文件的單元是字節(jié),所以它不但可以讀寫(xiě)文本文件,也可以讀寫(xiě)圖片、聲音、影像文件,這種特點(diǎn)非常有用,因?yàn)槲覀兛梢园堰@種文件變成流,然后在網(wǎng)絡(luò)上傳輸。 問(wèn)題是有了通用的流文件以后,為什么還要專門(mén)的字符流呢?這是因?yàn)槲谋究梢杂貌煌姆绞酱鎯?chǔ),可以是普通的文本(UTF-8編碼方式),ASCII文本和Unicode文本,字符流對(duì)象可以進(jìn)行必要的轉(zhuǎn)換,從而讀出正確的文本。 有人認(rèn)為流文件不能讀寫(xiě)文本文件,這其實(shí)是個(gè)誤會(huì),因?yàn)槲谋疚募举|(zhì)上也是由字節(jié)組成的,當(dāng)然是流文件的一種。作為讀寫(xiě)文件的全體,這是沒(méi)問(wèn)題的,但是,如果要處理每次讀入的內(nèi)容,就最好使用字符流。 所以在文本文件處理時(shí),使用字符流是個(gè)最常用的方法。 樣例: import java.io.*; public class FileStreamDemo { public static void main(String[] args) throws IOException { //創(chuàng)建兩個(gè)文件,face.gif是已經(jīng)存在文件,newFace.gif是新創(chuàng)建的文件 File inFile = new File("face.gif"); File outFile = new File("newFace.gif"); //創(chuàng)建流文件讀入與寫(xiě)出類 FileInputStream inStream = new FileInputStream(inFile); FileOutputStream outStream = new FileOutputStream(outFile); //通過(guò)available方法取得流的最大字符數(shù) byte[] inOutb = new byte[inStream.available()]; inStream.read(inOutb); //讀入流,保存在byte數(shù)組 outStream.write(inOutb); //寫(xiě)出流,保存在文件newFace.gif中 inStream.close(); outStream.close(); } } 實(shí)例:讀寫(xiě)任意大文件應(yīng)用 因?yàn)閎yte數(shù)組最大存儲(chǔ)值不超過(guò)64M,所以當(dāng)一個(gè)文件大于60M 的時(shí)候,需要分開(kāi)幾個(gè)流操作。我們把上面的程序作一個(gè)修改,就可以寫(xiě)入任意大小的文件。這個(gè)程序應(yīng)用了FileInputStream類的方法如下: read(byte[] b,int off,int len) 把特定位置的流內(nèi)容讀入數(shù)組,已經(jīng)讀入byte[]數(shù)組的內(nèi)容,會(huì)在流文件中刪除。 程序運(yùn)行的結(jié)果會(huì)產(chǎn)生一個(gè)新文件。 樣例: import java.io.*; public class FileStreamDemo2 { public static void main(String[] args) throws IOException { //創(chuàng)建兩個(gè)文件 File inFile = new File("tcty36.rm"); File outFile = new File("newtcty36.rm"); //最大的流為60Mb,當(dāng)文件的容量大于60Mb的時(shí)候便分開(kāi)流 final int MAX_BYTE = 60000000; long streamTotal = 0; //接受流的容量 int streamNum = 0; //流需要分開(kāi)的數(shù)量 int leave = 0; //文件剩下的字符數(shù) byte[] inOutb; //byte數(shù)組接受文件的數(shù)據(jù) //創(chuàng)建流文件讀入與寫(xiě)出類 FileInputStream inStream = new FileInputStream(inFile); FileOutputStream outStream = new FileOutputStream(outFile); //通過(guò)available方法取得流的最大字符數(shù) streamTotal = inStream.available(); //取得流文件需要分開(kāi)的數(shù)量 streamNum = (int)Math.floor(streamTotal/MAX_BYTE); //分開(kāi)文件之后,剩余的數(shù)量 leave = (int)streamTotal % MAX_BYTE; //文件的容量大于60Mb時(shí)進(jìn)入循環(huán) if (streamNum > 0) { for(int i = 0; i < streamNum; ++i){ inOutb = new byte[MAX_BYTE]; //讀入流,保存在byte數(shù)組 inStream.read(inOutb, 0, MAX_BYTE); outStream.write(inOutb); //寫(xiě)出流 outStream.flush(); //更新寫(xiě)出的結(jié)果 } } //寫(xiě)出剩下的流數(shù)據(jù) inOutb = new byte[leave]; inStream.read(inOutb, 0, leave); outStream.write(inOutb); outStream.flush(); inStream.close(); outStream.close(); } } 六、管道PipedInputStream/PipedOutputStream類: 當(dāng)需要在兩個(gè)線程中讀寫(xiě)數(shù)據(jù)的時(shí)候,由于線程的并發(fā)執(zhí)行,讀寫(xiě)的同步問(wèn)題可能會(huì)發(fā)生困難,這時(shí)候可以使用管道,管道事實(shí)上是一個(gè)隊(duì)列。 管道是由系統(tǒng)維護(hù)的一個(gè)緩沖區(qū),當(dāng)然程序員也可以自己直接指定該緩沖區(qū)的大?。ㄖ恍枰O(shè)置管道流類中的PIPE_SIZE屬性的值)。當(dāng)生產(chǎn)者生產(chǎn)出數(shù)據(jù)后,只需要將數(shù)據(jù)寫(xiě)入管道中,消費(fèi)者只需要從管道中讀取所需要的數(shù)據(jù)。利用管道的這種機(jī)制,可以將一個(gè)線程的輸出結(jié)果直接連接到另一個(gè)線程的輸入端口,實(shí)現(xiàn)兩者之間的數(shù)據(jù)直接傳送。 線程1 線程2 臨時(shí)文件 管道 1.管道的連接: 方法之一是通過(guò)構(gòu)造函數(shù)直接將某一個(gè)程序的輸出作為另一個(gè)程序的輸入,在定義對(duì)象時(shí)指明目標(biāo)管道對(duì)象 PipedInputStream pInput=new PipedInputStream(); PipedOutputStream pOutput= new PipedOutputStream(pInput); 方法之二是利用雙方類中的任一個(gè)成員函數(shù) connect()相連接 PipedInputStream pInput=new PipedInputStream(); PipedOutputStream pOutput= new PipedOutputStream(); pinput.connect(pOutput); 2.管道的輸入與輸出: 輸出管道對(duì)象調(diào)用write()成員函數(shù)輸出數(shù)據(jù)(即向管道的輸入端發(fā)送數(shù)據(jù));而輸入管道對(duì)象調(diào)用read()成員函數(shù)可以讀起數(shù)據(jù)(即從輸出管道中獲得數(shù)據(jù))。這主要是借助系統(tǒng)所提供的緩沖機(jī)制來(lái)實(shí)現(xiàn)的。 實(shí)例:Java的管道的輸入與輸出 import java.io.*; public class PipedIO //程序運(yùn)行后將sendFile文件的內(nèi)容拷貝到receiverFile文件中 { public static void main(String args[]) { try { //構(gòu)造讀寫(xiě)的管道流對(duì)象 PipedInputStream pis=new PipedInputStream(); PipedOutputStream pos=new PipedOutputStream(); //實(shí)現(xiàn)關(guān)聯(lián) pos.connect(pis); //構(gòu)造兩個(gè)線程,并且啟動(dòng)。 new Sender(pos,"c:\\text2.txt").start(); new Receiver(pis,"c:\\text3.txt").start(); } catch(IOException e) { System.out.println("Pipe Error"+ e); } } } //線程發(fā)送 class Sender extends Thread { PipedOutputStream pos; File file; //構(gòu)造方法 Sender(PipedOutputStream pos, String fileName) { this.pos=pos; file=new File(fileName); } //線程運(yùn)行方法 public void run() { try { //讀文件內(nèi)容 FileInputStream fs=new FileInputStream(file); int data; while((data=fs.read())!=-1) { //寫(xiě)入管道始端 pos.write(data); } pos.close(); } catch(IOException e) { System.out.println("Sender Error" +e); } } } //線程讀 class Receiver extends Thread { PipedInputStream pis; File file; //構(gòu)造方法 Receiver(PipedInputStream pis, String fileName) { this.pis=pis; file=new File(fileName); } //線程運(yùn)行 public void run() { try { //寫(xiě)文件流對(duì)象 FileOutputStream fs=new FileOutputStream(file); int data; //從管道末端讀 while((data=pis.read())!=-1) { //寫(xiě)入本地文件 fs.write(data); } pis.close(); } catch(IOException e) { System.out.println("Receiver Error" +e); } } } 七、隨機(jī)文件讀寫(xiě):RandomAccessFile類 它直接繼承于Object類而非InputStream/OutputStream類,從而可以實(shí)現(xiàn)讀寫(xiě)文件中任何位置中的數(shù)據(jù)(只需要改變文件的讀寫(xiě)位置的指針)。 編程步驟: ① 生成流對(duì)象并且指明讀寫(xiě)類型; ② 移動(dòng)讀寫(xiě)位置; ③ 讀寫(xiě)文件內(nèi)容; ④ 關(guān)閉文件。 另外由于RandomAccessFile類實(shí)現(xiàn)了DataOutput與DataInput接口,因而利用它可以讀寫(xiě)Java中的不同類型的基本類型數(shù)據(jù)(比如采用readLong()方法讀取長(zhǎng)整數(shù),而利用readInt()方法可以讀出整數(shù)值等)。 程序?qū)嵗?nbsp; 利用隨機(jī)數(shù)據(jù)流RandomAccessFile類來(lái)實(shí)現(xiàn)記錄用戶在鍵盤(pán)的輸入,每執(zhí)行一次,將用戶的鍵盤(pán)輸入存儲(chǔ)在指定的UserInput.txt文件中。 import java.io.*; public class RandomFileRW { public static void main(String args[]) { StringBuffer buf=new StringBuffer(); char ch; try { while( (ch=(char)System.in.read()) !='\n') { buf.append(ch); } //讀寫(xiě)方式可以為"r" or "rw" RandomAccessFile myFileStream=new RandomAccessFile("c:\\UserInput.txt","rw"); myFileStream.seek(myFileStream.length()) ; myFileStream.writeBytes(buf.toString()); //將用戶從鍵盤(pán)輸入的內(nèi)容添加到文件的尾部 myFileStream.close(); } catch(IOException e) { } } } 八、DataInput/DataOutput接口: 實(shí)現(xiàn)與機(jī)器無(wú)關(guān)的各種數(shù)據(jù)格式讀寫(xiě)(如readChar() 、readInt()、readLong()、readFloat(),而readLine()將返回一個(gè)String)。其中 RandomAccessFile類實(shí)現(xiàn)了該接口,具有比FileInputStream或FileOutputStream類更靈活的數(shù)據(jù)讀寫(xiě)方式。 I.Linux C 創(chuàng)建目錄函數(shù)mkdir的mode設(shè)置問(wèn)題  函數(shù)原型: #include <sys/stat.h> int mkdir(const char *path, mode_t mode); 參數(shù): path是目錄名 mode是目錄權(quán)限 返回值: 返回0 表示成功, 返回 -1表示錯(cuò)誤,并且會(huì)設(shè)置errno值。 mode模式位: mode 表示新目錄的權(quán)限,可以取以下值: S_IRUSR S_IREAD S_IWUSR S_IWRITE S_IXUSR S_IEXEC S_IRWXU This is equivalent to (S_IRUSR | S_IWUSR | S_IXUSR). S_IRGRP Read permission bit for the group owner of the file. Usually 040. S_IWGRP Write permission bit for the group owner of the file. Usually 020. S_IXGRP Execute or search permission bit for the group owner of the file. Usually 010. S_IRWXG This is equivalent to (S_IRGRP | S_IWGRP | S_IXGRP). S_IROTH Read permission bit for other users. Usually 04. S_IWOTH Write permission bit for other users. Usually 02. S_IXOTH Execute or search permission bit for other users. Usually 01. S_IRWXO This is equivalent to (S_IROTH | S_IWOTH | S_IXOTH). S_ISUID This is the set-user-ID on execute bit, usually 04000. See How Change Persona. S_ISGID This is the set-group-ID on execute bit, usually 02000. See How Change Persona. S_ISVTX This is the sticky bit, usually 01000. 例子: #include <sys/types.h> #include <sys/stat.h> int status; status = mkdir("/home/newdir", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); 這樣就創(chuàng)建了一個(gè)newdir目錄,權(quán)限通過(guò)ls -al 查看為 drwxr-xr-x 跟用linux命令mkdir創(chuàng)建的目錄權(quán)限位一致。 II. linux下C語(yǔ)言創(chuàng)建多級(jí)目錄 int CreateDir(const char *sPathName) { char DirName[256]; strcpy(DirName, sPathName); int i,len = strlen(DirName); if(DirName[len-1]!='/') strcat(DirName, "/"); len = strlen(DirName); for(i=1; i<len; i++) { if(DirName[i]=='/') { DirName[i] = 0; if( access(DirName, NULL)!=0 ) { if(mkdir(DirName, 0755)==-1) { perror("mkdir error"); return -1; } } DirName[i] = '/'; } } return 0; } III.linux c 編程:創(chuàng)建一個(gè)線程,監(jiān)視某個(gè)目錄,一旦目錄里出現(xiàn)新的文件,就將文件轉(zhuǎn)移到指定的目錄里去。 /* 頭文件 */ #define SRCPATH "srcpath/" #define DSTPATH "dstpath/" int movefile() { DIR *dir; struct dirent *dt; FILE *fp1,*fp2; char filename1[256],filename2[256]; char buf[1024]; int readsize,writesize; if((dir = opendir(SRCPATH)) == NULL) { printf("opendir %s error\n",SRCPATH); return -1; } memset(filename1,0,sizeof(filename1)); strcpy(filename1,SRCPATH); memset(filename2,0,sizeof(filename2)); strcpy(filename2,DSTPATH); while(1) { while((dt = readdir(dir)) != NULL) { if(strcmp(dt->d_name,".")==0||strcmp(dt->d_name,"..")==0) { continue; } //如果這個(gè)目錄里 還有目錄,可以在這加判斷 //這里假設(shè)初始為空目錄 strcat(filename1,dt->d_name); strcat(filename2,dt->d_name); //如果進(jìn)程資源較少可以直接用linux系統(tǒng)命令 fp1 = fopen(filename1,"rb"); if(fp1==NULL) { printf("open %s failed /n",filename1); return -1; } fp2 = fopen(filename2,"wb"); if(fp2==NULL) { printf("open %s failed /n",filename2); fclose(fp1); return -1; } while((readsize = fread(buf,sizeof(buf),1,fp1))>0) { //total += readsize; memset(buf,0,sizeof(buf)); writesize = fwrite(buf,sizeof(buf),1,fp2); if(writesize!==readsize) { printf("write error"); return -2; fclose(fp1); fclose(fp2); } } fclose(fp1); fclose(fp2); rmdir(filename2); } } } int main(int argc,char **argv) { pthread_t id1; int ret; ret = pthread_create(&id1, NULL, (void*)movefile, NULL); return ret; } 1.Linux文件系統(tǒng)  Linux支持多種文件系統(tǒng),如ext、ext2、minix、iso9660、msdos、fat、vfat、nfs等。在這些具體文件系統(tǒng)的上層,Linux提供了虛擬文件系統(tǒng)(VFS)來(lái)統(tǒng)一它們的行為,虛擬文件系統(tǒng)為不同的文件系統(tǒng)與內(nèi)核的通信提供了一致的接口。 linux下的c語(yǔ)言開(kāi)發(fā) 在Linux平臺(tái)下對(duì)文件編程可以使用兩類函數(shù):(1)Linux操作系統(tǒng)文件API;(2)C語(yǔ)言I/O庫(kù)函數(shù)。 前者依賴于Linux系統(tǒng)調(diào)用,后者實(shí)際上與操作系統(tǒng)是獨(dú)立的,因?yàn)樵谌魏尾僮飨到y(tǒng)下,使用C語(yǔ)言I/O庫(kù)函數(shù)操作文件的方法都是相同的。本章將對(duì)這兩種方法進(jìn)行實(shí)例講解。 2.Linux文件API Linux的文件操作API涉及到創(chuàng)建、打開(kāi)、讀寫(xiě)和關(guān)閉文件。 創(chuàng)建 int creat(const char *filename, mode_t mode); 參數(shù)mode指定新建文件的存取權(quán)限,它同umask一起決定文件的最終權(quán)限(mode&umask),其中umask代表了文件在創(chuàng)建時(shí)需要去掉的一些存取權(quán)限。umask可通過(guò)系統(tǒng)調(diào)用umask()來(lái)改變: int umask(int newmask); 該調(diào)用將umask設(shè)置為newmask,然后返回舊的umask,它只影響讀、寫(xiě)和執(zhí)行權(quán)限。 打開(kāi) int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode); open函數(shù)有兩個(gè)形式,其中pathname是我們要打開(kāi)的文件名(包含路徑名稱,缺省是認(rèn)為在當(dāng)前路徑下面),flags可以去下面的一個(gè)值或者是幾個(gè)值的組合: 標(biāo)志 含義 O_RDONLY 以只讀的方式打開(kāi)文件 O_WRONLY 以只寫(xiě)的方式打開(kāi)文件 O_RDWR 以讀寫(xiě)的方式打開(kāi)文件 O_APPEND 以追加的方式打開(kāi)文件 O_CREAT 創(chuàng)建一個(gè)文件 O_EXEC 如果使用了O_CREAT而且文件已經(jīng)存在,就會(huì)發(fā)生一個(gè)錯(cuò)誤 O_NOBLOCK 以非阻塞的方式打開(kāi)一個(gè)文件 O_TRUNC 如果文件已經(jīng)存在,則刪除文件的內(nèi)容 O_RDONLY、O_WRONLY、O_RDWR三個(gè)標(biāo)志只能使用任意的一個(gè)。 如果使用了O_CREATE標(biāo)志,則使用的函數(shù)是int open(const char *pathname,int flags,mode_t mode); 這個(gè)時(shí)候我們還要指定mode標(biāo)志,用來(lái)表示文件的訪問(wèn)權(quán)限。mode可以是以下情況的組合: 標(biāo)志 含義 S_IRUSR 用戶可以讀 S_IWUSR 用戶可以寫(xiě) S_IXUSR 用戶可以執(zhí)行 S_IRWXU 用戶可以讀、寫(xiě)、執(zhí)行 S_IRGRP 組可以讀 S_IWGRP 組可以寫(xiě) S_IXGRP 組可以執(zhí)行 S_IRWXG 組可以讀寫(xiě)執(zhí)行 S_IROTH 其他人可以讀 S_IWOTH 其他人可以寫(xiě) S_IXOTH 其他人可以執(zhí)行 S_IRWXO 其他人可以讀、寫(xiě)、執(zhí)行 S_ISUID 設(shè)置用戶執(zhí)行ID S_ISGID 設(shè)置組的執(zhí)行ID 除了可以通過(guò)上述宏進(jìn)行“或”邏輯產(chǎn)生標(biāo)志以外,我們也可以自己用數(shù)字來(lái)表示,Linux總共用5個(gè)數(shù)字來(lái)表示文件的各種權(quán)限:第一位表示設(shè)置用戶ID;第二位表示設(shè)置組ID;第三位表示用戶自己的權(quán)限位;第四位表示組的權(quán)限;最后一位表示其他人的權(quán)限。每個(gè)數(shù)字可以取1(執(zhí)行權(quán)限)、2(寫(xiě)權(quán)限)、4(讀權(quán)限)、0(無(wú))或者是這些值的和。例如,要?jiǎng)?chuàng)建一個(gè)用戶可讀、可寫(xiě)、可執(zhí)行,但是組沒(méi)有權(quán)限,其他人可以讀、可以執(zhí)行的文件,并設(shè)置用戶ID位。那么,我們應(yīng)該使用的模式是1(設(shè)置用戶ID)、0(不設(shè)置組 ID)、7(1+2+4,讀、寫(xiě)、執(zhí)行)、0(沒(méi)有權(quán)限)、5(1+4,讀、執(zhí)行)即10705: open("test", O_CREAT, 10705); 上述語(yǔ)句等價(jià)于: open("test", O_CREAT, S_IRWXU | S_IROTH | S_IXOTH | S_ISUID ); 如果文件打開(kāi)成功,open函數(shù)會(huì)返回一個(gè)文件描述符,以后對(duì)該文件的所有操作就可以通過(guò)對(duì)這個(gè)文件描述符進(jìn)行操作來(lái)實(shí)現(xiàn)。 讀寫(xiě) 在文件打開(kāi)以后,我們才可對(duì)文件進(jìn)行讀寫(xiě)了,Linux中提供文件讀寫(xiě)的系統(tǒng)調(diào)用是read、write函數(shù): int read(int fd, const void *buf, size_t length); int write(int fd, const void *buf, size_t length); 其中參數(shù)buf為指向緩沖區(qū)的指針,length為緩沖區(qū)的大?。ㄒ宰止?jié)為單位)。函數(shù)read()實(shí)現(xiàn)從文件描述符fd所指定的文件中讀取 length個(gè)字節(jié)到buf所指向的緩沖區(qū)中,返回值為實(shí)際讀取的字節(jié)數(shù)。函數(shù)write實(shí)現(xiàn)將把length個(gè)字節(jié)從buf指向的緩沖區(qū)中寫(xiě)到文件描述符fd所指向的文件中,返回值為實(shí)際寫(xiě)入的字節(jié)數(shù)。 以O(shè)_CREAT為標(biāo)志的open實(shí)際上實(shí)現(xiàn)了文件創(chuàng)建的功能,因此,下面的函數(shù)等同creat()函數(shù): int open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode); 定位 對(duì)于隨機(jī)文件,我們可以隨機(jī)的指定位置讀寫(xiě),使用如下函數(shù)進(jìn)行定位: int lseek(int fd, offset_t offset, int whence); lseek()將文件讀寫(xiě)指針相對(duì)whence移動(dòng)offset個(gè)字節(jié)。操作成功時(shí),返回文件指針相對(duì)于文件頭的位置。參數(shù)whence可使用下述值: SEEK_SET:相對(duì)文件開(kāi)頭 SEEK_CUR:相對(duì)文件讀寫(xiě)指針的當(dāng)前位置 SEEK_END:相對(duì)文件末尾 offset可取負(fù)值,例如下述調(diào)用可將文件指針相對(duì)當(dāng)前位置向前移動(dòng)5個(gè)字節(jié): lseek(fd, -5, SEEK_CUR); 由于lseek函數(shù)的返回值為文件指針相對(duì)于文件頭的位置,因此下列調(diào)用的返回值就是文件的長(zhǎng)度: lseek(fd, 0, SEEK_END); 關(guān)閉 當(dāng)我們操作完成以后,我們要關(guān)閉文件了,只要調(diào)用close就可以了,其中fd是我們要關(guān)閉的文件描述符: int close(int fd); 例程:編寫(xiě)一個(gè)程序,在當(dāng)前目錄下創(chuàng)建用戶可讀寫(xiě)文件“hello.txt”,在其中寫(xiě)入“Hello, software weekly”,關(guān)閉該文件。再次打開(kāi)該文件,讀取其中的內(nèi)容并輸出在屏幕上。 #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #define LENGTH 100 main() { int fd, len; char str[LENGTH]; fd = open("hello.txt", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); /* 創(chuàng)建并打開(kāi)文件 */ if (fd) { write(fd, "Hello, Software Weekly", strlen("Hello, software weekly")); /* 寫(xiě)入 Hello, software weekly字符串 */ close(fd); } fd = open("hello.txt", O_RDWR); len = read(fd, str, LENGTH); /* 讀取文件內(nèi)容 */ str[len] = '\0'; printf("%s\n", str); close(fd); } 編譯并運(yùn)行,執(zhí)行結(jié)果如下圖: linux 3.C語(yǔ)言庫(kù)函數(shù) C庫(kù)函數(shù)的文件操作實(shí)際上是獨(dú)立于具體的操作系統(tǒng)平臺(tái)的,不管是在DOS、Windows、Linux還是在VxWorks中都是這些函數(shù): 創(chuàng)建和打開(kāi) FILE *fopen(const char *path, const char *mode); fopen()實(shí)現(xiàn)打開(kāi)指定文件filename,其中的mode為打開(kāi)模式,C語(yǔ)言中支持的打開(kāi)模式如下表: 標(biāo)志 含義 r, rb 以只讀方式打開(kāi) w, wb 以只寫(xiě)方式打開(kāi)。如果文件不存在,則創(chuàng)建該文件,否則文件被截?cái)?nbsp; a, ab 以追加方式打開(kāi)。如果文件不存在,則創(chuàng)建該文件 r+, r+b, rb+ 以讀寫(xiě)方式打開(kāi) w+, w+b, wh+ 以讀寫(xiě)方式打開(kāi)。如果文件不存在時(shí),創(chuàng)建新文件,否則文件被截?cái)?nbsp; a+, a+b, ab+ 以讀和追加方式打開(kāi)。如果文件不存在,創(chuàng)建新文件 其中b用于區(qū)分二進(jìn)制文件和文本文件,這一點(diǎn)在DOS、Windows系統(tǒng)中是有區(qū)分的,但Linux不區(qū)分二進(jìn)制文件和文本文件。 讀寫(xiě) C庫(kù)函數(shù)支持以字符、字符串等為單位,支持按照某中格式進(jìn)行文件的讀寫(xiě),這一組函數(shù)為: int fgetc(FILE *stream); int fputc(int c, FILE *stream); char *fgets(char *s, int n, FILE *stream); int fputs(const char *s, FILE *stream); int fprintf(FILE *stream, const char *format, ...); int fscanf (FILE *stream, const char *format, ...); size_t fread(void *ptr, size_t size, size_t n, FILE *stream); size_t fwrite (const void *ptr, size_t size, size_t n, FILE *stream); fread()實(shí)現(xiàn)從流stream中讀取加n個(gè)字段,每個(gè)字段為size字節(jié),并將讀取的字段放入ptr所指的字符數(shù)組中,返回實(shí)際已讀取的字段數(shù)。在讀取的字段數(shù)小于num時(shí),可能是在函數(shù)調(diào)用時(shí)出現(xiàn)錯(cuò)誤,也可能是讀到文件的結(jié)尾。所以要通過(guò)調(diào)用feof()和ferror()來(lái)判斷。 write()實(shí)現(xiàn)從緩沖區(qū)ptr所指的數(shù)組中把n個(gè)字段寫(xiě)到流stream中,每個(gè)字段長(zhǎng)為size個(gè)字節(jié),返回實(shí)際寫(xiě)入的字段數(shù)。 另外,C庫(kù)函數(shù)還提供了讀寫(xiě)過(guò)程中的定位能力,這些函數(shù)包括 int fgetpos(FILE *stream, fpos_t *pos); int fsetpos(FILE *stream, const fpos_t *pos); int fseek(FILE *stream, long offset, int whence); 等。 關(guān)閉 利用C庫(kù)函數(shù)關(guān)閉文件依然是很簡(jiǎn)單的操作: int fclose (FILE *stream); 例程:將第2節(jié)中的例程用C庫(kù)函數(shù)來(lái)實(shí)現(xiàn)。 #include <stdio.h> #define LENGTH 100 main() { FILE *fd; char str[LENGTH]; fd = fopen("hello.txt", "w+"); /* 創(chuàng)建并打開(kāi)文件 */ if (fd) { fputs("Hello, Software Weekly", fd); /* 寫(xiě)入Hello, software weekly字符串 */ fclose(fd); } fd = fopen("hello.txt", "r"); fgets(str, LENGTH, fd); /* 讀取文件內(nèi)容 */ printf("%s\n", str); fclose(fd); } 4.小結(jié) Linux提供的虛擬文件系統(tǒng)為多種文件系統(tǒng)提供了統(tǒng)一的接口,Linux的文件編程有兩種途徑:基于Linux系統(tǒng)調(diào)用;基于C庫(kù)函數(shù)。這兩種編程所涉及到文件操作有新建、打開(kāi)、讀寫(xiě)和關(guān)閉,對(duì)隨機(jī)文件還可以定位。本章對(duì)這兩種編程方法都給出了具體的實(shí)例。 首先感謝作者的工作,謝謝了,轉(zhuǎn)到這里都是我需要過(guò)的  =>#include <fcntl.h> =>/usr/include/bits/fcntl.h ,里面有 /* open/fcntl - O_SYNC is only implemented on blocks devices and on files located on an ext2 file system */ #define O_ACCMODE 0003 #define O_RDONLY 00 #define O_WRONLY 01 #define O_RDWR 02 #define O_CREAT 0100 /* not fcntl */ #define O_EXCL 0200 /* not fcntl */ #define O_NOCTTY 0400 /* not fcntl */ #define O_TRUNC 01000 /* not fcntl */ #define O_APPEND 02000 #define O_NONBLOCK 04000 #define O_NDELAY O_NONBLOCK #define O_SYNC 010000 #define O_FSYNC O_SYNC #define O_ASYNC 020000 摘要:本文簡(jiǎn)單介紹文件操作的三個(gè)函數(shù)(open,read,write)的基本用法。 詳細(xì)說(shuō)明了open函數(shù)的用法。 作者:zieckey (zieckey@yahoo.com.cn) All Rights Reserved! 所需頭文件: #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> 函數(shù)定義: int open( const char * pathname, int flags); int open( const char * pathname,int flags, mode_t mode); 函數(shù)說(shuō)明: 參數(shù) pathname 指向欲打開(kāi)的文件路徑字符串。下列是參數(shù) flags 所能使用的旗標(biāo): O_RDONLY 以只讀方式打開(kāi)文件 O_WRONLY 以只寫(xiě)方式打開(kāi)文件 O_RDWR以可讀寫(xiě)方式打開(kāi)文件。 上述三種旗標(biāo)是互斥的,也就是不可同時(shí)使用,但可與下列的旗標(biāo)利用 OR(|)運(yùn)算符組合。 O_CREAT 若欲打開(kāi)的文件不存在則自動(dòng)建立該文件。 O_EXCL 如果 O_CREAT 也被設(shè)置, 此指令會(huì)去檢查文件是否存在。文件若不存在則建立該文件, 否則將導(dǎo)致打開(kāi)文件錯(cuò)誤。 此外,若 O_CREAT 與 O_EXCL 同時(shí)設(shè)置, 并且欲打開(kāi)的文件為符號(hào)連接,則會(huì)打開(kāi)文件失敗。 O_NOCTTY 如果欲打開(kāi)的文件為終端機(jī)設(shè)備時(shí),則不會(huì)將該終端機(jī)當(dāng)成進(jìn)程控制終端機(jī)。 O_TRUNC 若文件存在并且以可寫(xiě)的方式打開(kāi)時(shí),此旗標(biāo)會(huì)令文件長(zhǎng)度清為 0,而原來(lái)存于該文件的資料也會(huì)消失。 O_APPEND 當(dāng)讀寫(xiě)文件時(shí)會(huì)從文件尾開(kāi)始移動(dòng), 也就是所寫(xiě)入的數(shù)據(jù)會(huì)以附加的方式加入到文件后面。 O_NONBLOCK 以不可阻斷的方式打開(kāi)文件,也就是無(wú)論有無(wú)數(shù)據(jù)讀取或等待,都會(huì)立即返回進(jìn)程之中。 O_NDELAY 同 O_NONBLOCK。 O_SYNC 以同步的方式打開(kāi)文件。 O_NOFOLLOW 如果參數(shù) pathname 所指的文件為一符號(hào)連接,則會(huì)令打開(kāi)文件失敗。 O_DIRECTORY 如果參數(shù) pathname 所指的文件并非為一目錄, 則 會(huì)令打開(kāi)文件失敗。此為 Linux2.2 以后特有的旗標(biāo),以避免一些系 統(tǒng)安全問(wèn)題。參數(shù) mode 則有下列數(shù)種組合,只有在建立新文件時(shí) 才會(huì)生效,此外真正建文件時(shí)的權(quán)限會(huì)受到 umask 值所影響,因此 該文件權(quán)限應(yīng)該為(mode-umaks). S_IRWXU00700 權(quán)限, 代表該文件所有者具有可讀、 可寫(xiě)及可執(zhí)行的權(quán)限。 S_IRUSR 或 S_IREAD,00400 權(quán)限,代表該文件所有者具有可讀取的權(quán)限。 S_IWUSR 或 S_IWRITE,00200 權(quán)限,代表該文件所有者具有可寫(xiě)入的權(quán)限。 S_IXUSR 或 S_IEXEC,00100 權(quán)限,代表該文件所有者具有可執(zhí)行的權(quán)限。 S_IRWXG 00070 權(quán)限,代表該文件用戶組具有可讀、 可寫(xiě)及可執(zhí)行的權(quán)限。 S_IRGRP 00040 權(quán)限,代表該文件用戶組具有可讀的權(quán)限。 S_IWGRP 00020 權(quán)限,代表該文件用戶組具有可寫(xiě)入的權(quán)限。 S_IXGRP 00010 權(quán)限,代表該文件用戶組具有可執(zhí)行的權(quán)限。 S_IRWXO 00007 權(quán)限,代表其他用戶具有可讀、可寫(xiě)及可執(zhí)行的權(quán)限。 S_IROTH 00004 權(quán)限,代表其他用戶具有可讀的權(quán)限 S_IWOTH 00002 權(quán)限,代表其他用戶具有可寫(xiě)入的權(quán)限。 S_IXOTH 00001 權(quán)限,代表其他用戶具有可執(zhí)行的權(quán)限。 返回值: 若所有欲核查的權(quán)限都通過(guò)了檢查則返回 0 值,表示成功,只要有 一個(gè)權(quán)限被禁止則返回-1。 錯(cuò)誤代碼: EEXIST 參數(shù) pathname 所指的文件已存在,卻使用了 O_CREAT和 O_EXCL 旗標(biāo) EACCESS 參數(shù) pathname 所指的文件不符合所要求測(cè)試的權(quán)限。 EROFS 欲測(cè)試寫(xiě)入權(quán)限的文件存在于只讀文件系統(tǒng)內(nèi)。 EFAULT 參數(shù) pathname 指針超出可存取內(nèi)存空間。 EINVAL 參數(shù) mode 不正確。 ENAMETOOLONG 參數(shù) pathname 太長(zhǎng)。 ENOTDIR 參數(shù) pathname 不是目錄。 ENOMEM 核心內(nèi)存不足。 ELOOP 參數(shù) pathname 有過(guò)多符號(hào)連接問(wèn)題。 EIO I/O 存取錯(cuò)誤。 范例: #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> int main(void) { int fd,size; char s[]="This program is used to show how to use open(),write(),read() function.\nHave fun!\n"; char buffer[80]; fd = open( "temp.log", O_WRONLY|O_CREAT );//以可讀寫(xiě)的方式打開(kāi)一個(gè)文件,如果不存在則創(chuàng)建該文件 if ( -1 == fd ) { printf("Open or create file named \"temp.log\" failed.\n"); return -1; } write( fd, s, sizeof(s) );//向該文件中寫(xiě)入一個(gè)字符串 close( fd ); fd = open( "temp.log", O_RDONLY ); if ( -1 == fd ) { printf("Open file named \"temp.log\" failed.\n"); return -1; } size = read( fd, buffer, sizeof(buffer) );//讀取文件內(nèi)容保存到buffer指定的字符串?dāng)?shù)組中,返回讀取的字符個(gè)數(shù) close( fd ); printf( "%s", buffer ); return 0; } 一、       從resource中的raw文件夾中獲取文件并讀取數(shù)據(jù)(資源文件只能讀不能寫(xiě))  String res = ""; try{ InputStream in = getResources().openRawResource(R.raw.bbi); //在\Test\res\raw\bbi.txt, int length = in.available(); byte [] buffer = new byte[length]; in.read(buffer); //res = EncodingUtils.getString(buffer, "UTF-8"); //res = EncodingUtils.getString(buffer, "UNICODE"); res = EncodingUtils.getString(buffer, "BIG5"); //依bbi.txt的編碼類型選擇合適的編碼,如果不調(diào)整會(huì)亂碼 in.close(); }catch(Exception e){ e.printStackTrace(); } myTextView.setText(res);//把得到的內(nèi)容顯示在TextView上 二、 從asset中獲取文件并讀取數(shù)據(jù)(資源文件只能讀不能寫(xiě)) String fileName = "yan.txt"; //文件名字 String res=""; try{ InputStream in = getResources().getAssets().open(fileName); // \Test\assets\yan.txt這里有這樣的文件存在 int length = in.available(); byte [] buffer = new byte[length]; in.read(buffer); res = EncodingUtils.getString(buffer, "UTF-8"); }catch(Exception e){ e.printStackTrace(); } 三、 從sdcard中去讀文件,首先要把文件通過(guò)\android-sdk-windows\tools\adb.exe把本地計(jì)算機(jī)上的文件copy到sdcard上去,adb.exe push e:/Y.txt /sdcard/, 不可以用adb.exe push e:\Y.txt \sdcard\ 同樣: 把仿真器上的文件copy到本地計(jì)算機(jī)上用: adb pull ./data/data/com.tt/files/Test.txt e:/ String fileName = "/sdcard/Y.txt"; //也可以用String fileName = "mnt/sdcard/Y.txt"; String res=""; try{ FileInputStream fin = new FileInputStream(fileName); //FileInputStream fin = openFileInput(fileName); //用這個(gè)就不行了,必須用FileInputStream int length = fin.available(); byte [] buffer = new byte[length]; fin.read(buffer); res = EncodingUtils.getString(buffer, "UTF-8"); fin.close(); }catch(Exception e){ e.printStackTrace(); } myTextView.setText(res); 四、 寫(xiě)文件, 一般寫(xiě)在\data\data\com.test\files\里面,打開(kāi)DDMS查看file explorer是可以看到仿真器文件存放目錄的結(jié)構(gòu)的 String fileName = "TEST.txt"; String message = "FFFFFFF11111FFFFF" ; writeFileData(fileName, message); public voidwriteFileData(String fileName,String message){ try{ FileOutputStream fout =openFileOutput(fileName, MODE_PRIVATE); byte [] bytes = message.getBytes(); fout.write(bytes); fout.close(); } catch(Exception e){ e.printStackTrace(); } } 五、 寫(xiě), 讀data/data/目錄(相當(dāng)AP工作目錄)上的文件,用openFileOutput //寫(xiě)文件在./data/data/com.tt/files/下面 public voidwriteFileData(String fileName,String message){ try{ FileOutputStream fout =openFileOutput(fileName, MODE_PRIVATE); byte [] bytes = message.getBytes(); fout.write(bytes); fout.close(); } catch(Exception e){ e.printStackTrace(); } } //------------------------------------------------------- //讀文件在./data/data/com.tt/files/下面 public String readFileData(String fileName){ String res=""; try{ FileInputStream fin = openFileInput(fileName); int length = fin.available(); byte [] buffer = new byte[length]; fin.read(buffer); res = EncodingUtils.getString(buffer, "UTF-8"); fin.close(); } catch(Exception e){ e.printStackTrace(); } return res; } 六、 寫(xiě), 讀sdcard目錄上的文件,要用FileOutputStream, 不能用openFileOutput //寫(xiě)在/mnt/sdcard/目錄下面的文件 public voidwriteFileSdcard(String fileName,String message){ try{ //FileOutputStream fout = openFileOutput(fileName, MODE_PRIVATE); FileOutputStream fout = newFileOutputStream(fileName); byte [] bytes = message.getBytes(); fout.write(bytes); fout.close(); } catch(Exception e){ e.printStackTrace(); } } //讀在/mnt/sdcard/目錄下面的文件 public String readFileSdcard(String fileName){ String res=""; try{ FileInputStream fin = new FileInputStream(fileName); int length = fin.available(); byte [] buffer = new byte[length]; fin.read(buffer); res = EncodingUtils.getString(buffer, "UTF-8"); fin.close(); } catch(Exception e){ e.printStackTrace(); } return res; } 注: openFileOutput是在raw里編譯過(guò)的,F(xiàn)ileOutputStream是任何文件都可以 參考:http://dev.10086.cn/cmdn/wiki/index.php?doc-view-6017.html 
                         asc碼對(duì)照表  ------------------------------------------------------------- ASCII Characters Dec Hex Char Code Dec Hex Char 0 0 NUL 64 40 @ 1 1 SOH 65 41 A 2 2 STX 66 42 B 3 3 ETX 67 43 C 4 4 EOT 68 44 D 5 5 ENQ 69 45 E 6 6 ACK 70 46 F 7 7 BEL 71 47 G 8 8 BS 72 48 H 9 9 HT 73 49 I 10 0A LF 74 4A J 11 0B VT 75 4B K 12 0C FF 76 4C L 13 0D CR 77 4D M 14 0E SO 78 4E N 15 0F SI 79 4F O 16 10 SLE 80 50 P 17 11 CS1 81 51 Q 18 12 DC2 82 52 R 19 13 DC3 83 53 S 20 14 DC4 84 54 T 21 15 NAK 85 55 U 22 16 SYN 86 56 V 23 17 ETB 87 57 W 24 18 CAN 88 58 X 25 19 EM 89 59 Y 26 1A SIB 90 5A Z 27 1B ESC 91 5B [ 28 1C FS 92 5C / 29 1D GS 93 5D ] 30 1E RS 94 5E ^ 31 1F US 95 5F _ 32 20 (space) 96 60 ` 33 21 ! 97 61 a 34 22 " 98 62 b 35 23 # 99 63 c 36 24 $ 100 64 d 37 25 % 101 65 e 38 26 & 102 66 f 39 27 ' 103 67 g 40 28 ( 104 68 h 41 29 ) 105 69 i 42 2A * 106 6A j 43 2B + 107 6B k 44 2C , 108 6C l 45 2D - 109 6D m 46 2E . 110 6E n 47 2F / 111 6F o 48 30 0 112 70 p 49 31 1 113 72 q 50 32 2 114 72 r 51 33 3 115 73 s 52 34 4 116 74 t 53 35 5 117 75 u 54 36 6 118 76 v 55 37 7 119 77 w 56 38 8 120 78 x 57 39 9 121 79 y 58 3A : 122 7A z 59 3B ; 123 7B { 60 3C < 124 7C | 61 3D = 125 7D } 62 3E > 126 7E ~ 63 3F ? 127 7F 目前計(jì)算機(jī)中用得最廣泛的字符集及其編碼,是由美國(guó)國(guó)家標(biāo)準(zhǔn)局(ANSI)制定的ASCII碼(American Standard Code for Information Interchange,美國(guó)標(biāo)準(zhǔn)信息交換碼),它已被國(guó)際標(biāo)準(zhǔn)化組織(ISO)定為國(guó)際標(biāo)準(zhǔn),稱為ISO 646標(biāo)準(zhǔn)。適用于所有拉丁文字字母,ASCII碼有7位碼和8位碼兩種形式。 因?yàn)?位二進(jìn)制數(shù)可以表示(21=)2種狀態(tài):0、1;而2位二進(jìn)制數(shù)可以表示(22)=4種狀態(tài):00、01、10、11;依次類推,7位二進(jìn)制數(shù)可以表示(27=)128種狀態(tài),每種狀態(tài)都唯一地編為一個(gè)7位的二進(jìn)制碼,對(duì)應(yīng)一個(gè)字符(或控制碼),這些碼可以排列成一個(gè)十進(jìn)制序號(hào)0~127。所以,7位 ASCII碼是用七位二進(jìn)制數(shù)進(jìn)行編碼的,可以表示128個(gè)字符。 第0~32號(hào)及第127號(hào)(共34個(gè))是控制字符或通訊專用字符,如控制符:LF(換行)、CR(回車(chē))、FF(換頁(yè))、DEL(刪除)、BEL(振鈴)等;通訊專用字符:SOH(文頭)、EOT(文尾)、ACK(確認(rèn))等; 第33~126號(hào)(共94個(gè))是字符,其中第48~57號(hào)為0~9十個(gè)阿拉伯?dāng)?shù)字;65~90號(hào)為26個(gè)大寫(xiě)英文字母,97~122號(hào)為26個(gè)小寫(xiě)英文字母,其余為一些標(biāo)點(diǎn)符號(hào)、運(yùn)算符號(hào)等。 注意:在計(jì)算機(jī)的存儲(chǔ)單元中,一個(gè)ASCII碼值占一個(gè)字節(jié)(8個(gè)二進(jìn)制位),其最高位(b7)用作奇偶校驗(yàn)位。所謂奇偶校驗(yàn),是指在代碼傳送過(guò)程中用來(lái)檢驗(yàn)是否出現(xiàn)錯(cuò)誤的一種方法,一般分奇校驗(yàn)和偶校驗(yàn)兩種。奇校驗(yàn)規(guī)定:正確的代碼一個(gè)字節(jié)中1的個(gè)數(shù)必須是奇數(shù),若非奇數(shù),則在最高位b7添1;偶校驗(yàn)規(guī)定:正確的代碼一個(gè)字節(jié)中1的個(gè)數(shù)必須是偶數(shù),若非偶數(shù),則在最高位b7添1。 第128~255號(hào)為擴(kuò)展字符(不常用),如需要請(qǐng)下載:完整的8位ASCII字符表  Android2.3的輸入事件流程與以前版本有了較大的不同,這里做一下詳細(xì)的分析,最后我把自己分析時(shí)用的演示代碼放在了這里:  http://code.google.com/p/flying-on-android/ 下面的分析都是基于這些源碼的,大家可以下載下來(lái)一邊看源碼一邊看文檔。源碼里只要關(guān)注FlyingEvent這個(gè)類就可以了。如果只想看一下演示結(jié)果,可以直接把包里的flying放到機(jī)器的/system/bin目錄執(zhí)行,打開(kāi)logcat后就可以看到演示輸出。運(yùn)行程序時(shí),機(jī)器屏幕會(huì)有異象產(chǎn)生,很正常,因?yàn)檫@個(gè)程序原本是用于顯示SurfaceFlinger的,這次為了演示EventHub稍微改了一下。大家只要關(guān)注 FlyingEvent.cpp這個(gè)文件就好了。 大家也可以用源碼自己編譯出演示程序,只要把解壓后的flying文件夾放到/frameworks/base/cmds/目錄下,然后切換到flying目錄下使用mm編譯。 先大致介紹一下整個(gè)流程,再做重點(diǎn)分析。輸入事件流程一共涉及到下面這幾個(gè)文件: /frameworks/base/services/java/com/android/server/WindowManagerService.java /frameworks/base/services/java/com/android/server/InputManager.java /frameworks/base/services/jni/com_android_server_InputManager.cpp /frameworks/base/libs/ui/InputReader.cpp /frameworks/base/libs/ui/InputDispatcher.cpp /frameworks/base/libs/ui/EventHub.cpp 其中,WindowManagerService.java和InputManager.java主要向Android為窗口系統(tǒng)提供服務(wù),EventHub.cpp主要用來(lái)讀取設(shè)備文件中的RawEvent,而InputReader.cpp和InputDispatcher.cpp算是它們之間的對(duì)接層。 它們的關(guān)系是:WindowManagerService通過(guò)InputManager提供的接口開(kāi)啟一個(gè)線程驅(qū)動(dòng)InputReader不斷地從 /dev/input/目錄下面的設(shè)備文件讀取事件,然后通過(guò)InputDispatcher分發(fā)給連接到WindowManagerService服務(wù)的客戶端。 InputReader從設(shè)備文件中讀取的是RawEvent,在交給InputDispatcher進(jìn)行分發(fā)之前,它需要先把RawEvent進(jìn)行轉(zhuǎn)化分類,拆分成KeyEvent、MotionEvent、TrackEvent各種類型等。這篇文章主要關(guān)注的就是這個(gè)RawEvent的拆分過(guò)程,所以我們的重點(diǎn)在EventHub.cpp中。并且,為了簡(jiǎn)單化分析過(guò)程,在這里我的分析只關(guān)注觸摸屏事件??此侨绾螐腞awEvent被拆分成應(yīng)用層用戶事件MotionEvent的。 看下面的分析之前,最好先去上面提到的地址把源碼下載下來(lái),參照里面的FlyingEvent.cpp。 整個(gè)過(guò)程大致分成這么幾步: 一、初始化。 先new一個(gè)EventHub的實(shí)例:mEventHub(new EventHub), 接下來(lái),開(kāi)啟一個(gè)線程通過(guò)mEventHub不停地從設(shè)備文件中讀取RawEvent并處理: while (1) { RawEvent event; mEventHub->getEvent(&event); process(event); } EventHub在初始化的時(shí)候做一些事情, 1、搜索當(dāng)前的輸入設(shè)備每搜索到一個(gè)就會(huì)產(chǎn)生一個(gè)類型為DEVICE_ADDED的事件,當(dāng)讀取這種RawEvent時(shí),InputReader會(huì)把搜索到的這個(gè)設(shè)備記錄下來(lái)。 2、如果搜索到了鍵盤(pán)時(shí),就會(huì)加載鍵盤(pán)布局文件。加載完成后產(chǎn)生一個(gè)類型為FINISHED_DEVICE_SCAN的事件。這樣,后邊從驅(qū)動(dòng)讀取用戶按鍵時(shí),就會(huì)去加載的鍵盤(pán)布局文件中尋找映射的鍵值封裝成KeyEvent返回給用戶。 二、EventHub初始化完畢后,就開(kāi)始等待用戶輸入。線程一直阻塞在mEventHub->getEvent(&event),直到有用戶事件產(chǎn)生才會(huì)返回。 當(dāng)有一個(gè)事件產(chǎn)生時(shí),傳遞給process進(jìn)行處理。 三、事件拆分 FlyingEvent.process里面主要調(diào)用了FlyingEvent.consume方法來(lái)處理用戶事件。這里只分析touch事件。touch事件可以分為三種:down,move,up。 down類型的touch事件需要四個(gè)RawEvent來(lái)完成,第一個(gè)是X坐標(biāo)(ABS_X),第二個(gè)是Y坐標(biāo)(ABS_Y),第三個(gè)代表方向(ABS_PRESSURE)(0的時(shí)候是up,1的時(shí)候是down,所以這里應(yīng)該是1),第四個(gè)是結(jié)束標(biāo)志(SYN_REPORT)。 move類型的touch事件需要三個(gè)RawEvent來(lái)完成,第一個(gè)是X坐標(biāo),第二個(gè)是Y坐標(biāo),第三個(gè)是結(jié)束標(biāo)志。 up類型的touch事件需要兩個(gè)RawEvent來(lái)完成,第一個(gè)代表方向(0的時(shí)候是up,1的時(shí)候是down,所以這里應(yīng)該是0),第四個(gè)是結(jié)束標(biāo)志。 可能你已經(jīng)注意到了up事件是沒(méi)有坐標(biāo)信息的,它的坐標(biāo)信息與down(沒(méi)有move時(shí))或最后一個(gè)move(down和up之間有move事件產(chǎn)生)事件的坐標(biāo)相同。 從FlyingEvent.consume方法中,每一個(gè)事件最終都會(huì)生成一個(gè)TouchEvent,然后調(diào)用printTouchEvent進(jìn)行打印,最后把它存儲(chǔ)到eventBuffer中。 參考文章 李先靜的“Android輸入事件流程“,不過(guò)使用的Android版本比較老了。 http://blog.csdn.net/absurd/archive/2009/05/17/4195363.aspx (摘自:http://blog.csdn.net/a345017062/article/details/6417929) 
 1.對(duì)文件和目錄的修改還原  svn revert PATH... 描述 恢復(fù)所有對(duì)文件和目錄的修改,并且解決所有的沖突狀態(tài)。svn revert不會(huì)只是恢復(fù)工作拷貝中一個(gè)項(xiàng)目的內(nèi)容,也包括了對(duì)屬性修改的恢復(fù)。最終,你可以使用它來(lái)取消所有已經(jīng)做過(guò)的預(yù)定操作(例如,文件預(yù)定要添加或刪除可以“恢復(fù)”)。 例子 丟棄對(duì)一個(gè)文件的修改: $ svn revert foo.c Reverted foo.c 如果你希望恢復(fù)一整個(gè)目錄的文件,可以使用--recursive選項(xiàng): $ svn revert --recursive . Reverted newdir/afile Reverted foo.c Reverted bar.txt 2.還原到以前版本 svn update -r 200 test.php(將版本庫(kù)中的文件test.php還原到版本200) 3.列出本地與SVN當(dāng)前版本差異 svn status -v path(顯示文件和子目錄狀態(tài)) 簡(jiǎn)寫(xiě):svn st 第一列保持相同,第二列顯示工作版本號(hào),第三和第四列顯示最后一次修改的版本號(hào)和修改人。 另外,可執(zhí)行script -q tty.log后,就開(kāi)始記錄終端的輸入輸出信息,結(jié)束的時(shí)候按ctrl+D即可得到終端的內(nèi)容文件tty.log 4. svn比較差異 svn diff path(將修改的文件與基礎(chǔ)版本比較) 例如:svn diff test.php svn diff -r m:n path(對(duì)版本m和版本n比較差異) 注:svn status、svn diff和 svn revert這三條命令在沒(méi)有網(wǎng)絡(luò)的情況下也可以執(zhí)行的,原因是svn在本地的.svn中保留了本地版本的原始拷貝。 在Linux下查看內(nèi)存我們一般用free命令:  [root@scs-2 tmp]# free total used free shared buffers cached Mem: 3266180 3250004 16176 0 110652 2668236 -/+ buffers/cache: 471116 2795064 Swap: 2048276 80160 1968116 下面是對(duì)這些數(shù)值的解釋: total:總計(jì)物理內(nèi)存的大小。 used:已使用多大。 free:可用有多少。 Shared:多個(gè)進(jìn)程共享的內(nèi)存總額。 Buffers/cached:磁盤(pán)緩存的大小。 第三行(-/+ buffers/cached): used:已使用多大。 free:可用有多少。 第四行就不多解釋了。 區(qū)別:第二行(mem)的used/free與第三行(-/+ buffers/cache) used/free的區(qū)別。 這兩個(gè)的區(qū)別在于使用的角度來(lái)看,第一行是從OS的角度來(lái)看,因?yàn)閷?duì)于OS,buffers/cached 都是屬于被使用,所以他的可用內(nèi)存是16176KB,已用內(nèi)存是3250004KB,其中包括,內(nèi)核(OS)使用+Application(X, oracle,etc)使用的+buffers+cached. 第三行所指的是從應(yīng)用程序角度來(lái)看,對(duì)于應(yīng)用程序來(lái)說(shuō),buffers/cached 是等于可用的,因?yàn)閎uffer/cached是為了提高文件讀取的性能,當(dāng)應(yīng)用程序需在用到內(nèi)存的時(shí)候,buffer/cached會(huì)很快地被回收。 所以從應(yīng)用程序的角度來(lái)說(shuō),可用內(nèi)存=系統(tǒng)free memory+buffers+cached。 如上例: 2795064=16176+110652+2668236 接下來(lái)解釋什么時(shí)候內(nèi)存會(huì)被交換,以及按什么方交換。 當(dāng)可用內(nèi)存少于額定值的時(shí)候,就會(huì)開(kāi)會(huì)進(jìn)行交換。 如何看額定值: cat /proc/meminfo [root@scs-2 tmp]# cat /proc/meminfo MemTotal: 3266180 kB MemFree: 17456 kB Buffers: 111328 kB Cached: 2664024 kB SwapCached: 0 kB Active: 467236 kB Inactive: 2644928 kB HighTotal: 0 kB HighFree: 0 kB LowTotal: 3266180 kB LowFree: 17456 kB SwapTotal: 2048276 kB SwapFree: 1968116 kB Dirty: 8 kB Writeback: 0 kB Mapped: 345360 kB Slab: 112344 kB Committed_AS: 535292 kB PageTables: 2340 kB VmallocTotal: 536870911 kB VmallocUsed: 272696 kB VmallocChunk: 536598175 kB HugePages_Total: 0 HugePages_Free: 0 Hugepagesize: 2048 kB 用free -m查看的結(jié)果: [root@scs-2 tmp]# free -m total used free shared buffers cached Mem: 3189 3173 16 0 107 2605 -/+ buffers/cache: 460 2729 Swap: 2000 78 1921 查看/proc/kcore文件的大?。▋?nèi)存鏡像): [root@scs-2 tmp]# ll -h /proc/kcore -r-------- 1 root root 4.1G Jun 12 12:04 /proc/kcore 備注: 占用內(nèi)存的測(cè)量 測(cè)量一個(gè)進(jìn)程占用了多少內(nèi)存,linux為我們提供了一個(gè)很方便的方法,/proc目錄為我們提供了所有的信息,實(shí)際上top等工具也通過(guò)這里來(lái)獲取相應(yīng)的信息。 /proc/meminfo 機(jī)器的內(nèi)存使用信息 /proc/pid/maps pid為進(jìn)程號(hào),顯示當(dāng)前進(jìn)程所占用的虛擬地址。 /proc/pid/statm 進(jìn)程所占用的內(nèi)存 [root@localhost ~]# cat /proc/self/statm 654 57 44 0 0 334 0 輸出解釋 CPU 以及CPU0。。。的每行的每個(gè)參數(shù)意思(以第一行為例)為: 參數(shù) 解釋 /proc//status Size (pages) 任務(wù)虛擬地址空間的大小 VmSize/4 Resident(pages) 應(yīng)用程序正在使用的物理內(nèi)存的大小 VmRSS/4 Shared(pages) 共享頁(yè)數(shù) 0 Trs(pages) 程序所擁有的可執(zhí)行虛擬內(nèi)存的大小 VmExe/4 Lrs(pages) 被映像到任務(wù)的虛擬內(nèi)存空間的庫(kù)的大小 VmLib/4 Drs(pages) 程序數(shù)據(jù)段和用戶態(tài)的棧的大小 (VmData+ VmStk )4 dt(pages) 04 查看機(jī)器可用內(nèi)存 /proc/28248/>free total used free shared buffers cached Mem: 1023788 926400 97388 0 134668 503688 -/+ buffers/cache: 288044 735744 Swap: 1959920 89608 1870312 我們通過(guò)free命令查看機(jī)器空閑內(nèi)存時(shí),會(huì)發(fā)現(xiàn)free的值很小。這主要是因?yàn)?,在linux中有這么一種思想,內(nèi)存不用白不用,因此它盡可能的cache和buffer一些數(shù)據(jù),以方便下次使用。但實(shí)際上這些內(nèi)存也是可以立刻拿來(lái)使用的。 所以 空閑內(nèi)存=free+buffers+cached=total-used 
 一:update.zip包的制作  1:新建一個(gè)目標(biāo),在此目錄下準(zhǔn)備好需要的文件,如system目錄文件、boot.img、recovery.img等. mkdir testupdate cp system/ testupdate/ -tf 注:如果文件是system.img鏡像可以用unyaffs解壓出來(lái)得到system 2:用make-update-script工具生成update-script腳本,如下 cp make-update-script testupdate/ cp android-info.txt testupdate/ cd testupdate ./make-update-script system android-info.txt > update-script rm make-update-script android-info.txt vi update-script //根據(jù)需要適當(dāng)修改些腳本 說(shuō)明:system是要更新的目錄,android-info.txt是板的版本信息,update-script是輸出文件名 3:建立一個(gè)目錄名稱為META-INF/com/google/android,把上面生成的腳本放進(jìn)去 mkdir -p META-INF/com/google/android mv update-script META-INF/com/google/android/ 4:壓縮文件 zip -r update.zip system META-INF 5:給壓縮文件添加簽名 mv update.zip ../signapk/ cd ../signapk/ java -jar signapk.jar testkey.x509.pem testkey.pk8 update.zip signed-update.zip 6:刪除多余的文件,并把生成的包重命名 rm update.zip mv signed-update.zip ../update.zip cd ../ 7:大功告成,把更新包update.zip拷到sdcard根目錄下去驗(yàn)證吧! 注意: 1)如果文件里有連接,應(yīng)該在獲取update-script之后在原文件里刪除鏈接文件,再打包,否則symlink將出錯(cuò); 2)如果原文件里有空目錄,所獲的簽名將失去此記錄,所以如果空目錄必須存在,更新之后的文件將與原文件不同(少了空目錄) 二:ramdisk.img 制作 方法1: 解壓: 1) mv ramdisk.img ramdisk.img.gz 2) gunzip ramdisk,img.gz 3) mkdir ramdisk;cd ramdisk 4) cpio -i -F ../ramdisk.img 壓縮: 1) 產(chǎn)生要pack的目錄list,也可以自己列 cpio -i -t -F ../ramdisk.img > list 2) 利用剛生成的list文件列表,cpio歸檔 cpio -o -H newc -O new.img < list 3) gzip new.img 方法2: 解壓: gunzip -c ../your-ramdisk-file | cpio -i 壓縮: find . | cpio -o -H newc | gzip > ../newramdisk.cpio.gz 注意:在android里的做法是 1)先得到ramdisk所需要的文件,比如root目錄 2)用mkbootfs制作ramdisk.img,用法如下 mkbootfs root | gzip > ramdisk.img 這里需要驗(yàn)證哪個(gè)能用android寫(xiě)下去 三:boot.img的制作 1:android正常做法 1):連接 mkbootimg --kernel your-kernel-file --ramdisk newramdisk.cpio.gz --cmdline "mem=128 console=ttymxc0,115200n8 init=/init rw" --output mynewimage.img 或 mkbootimg --kernel your-kernel-file --ramdisk newramdisk.cpio.gz --cmdline --output mynewimage.img 2):提取img中的kernel和ramdisk ./split_bootimg.pl mynewimage.img 2:uboot 直接把uImage重命名為boot.img即可 四:system.img的制作(只為 yaffs2格式) 1)壓制:./mkyaffs2image system/ system.img 2)解壓:./unyaffs system.img 四:system.img的制作(只為yaffs2格式) 1)壓制:./mkyaffs2image system/ system.img 2)解壓:./unyaffs system.img 五:recovery.img的制作 1:如果recovery的鏡像是只有文件系統(tǒng)部分時(shí)候可以如第四所示范 2:如果recovery為ramdisk形式 ============================================= 制 作ramdisk的過(guò)程。 1.在/mnt下創(chuàng)建rdmnt 和 rdimg 目錄 mkdir rdmnt mkdir rdimg 2.創(chuàng)建一個(gè)ramdisk文件,大小32768 X 1k。 dd if=/dev/zero of=rdimg/ramdisk bs=1k count=32768 3.使用ext2方式格式該文件 mke2fs -F -v -m0 rdimg/ramdisk 4.將該ramdisk文件和rdmnt掛載 mount -o loop rdimg/ramdisk rdmnt/ 5.拷貝文件到掛載目錄中。 文件系統(tǒng)目錄在:/home/xrqun/workdir/filesys/ cp –av /home/xrqun/workdir/filesys/* rdmnt 6.卸載ramdisk umount rdmnt 7壓縮 ramdisk文件 gzip –c -9 <rdimg/ramdisk > rdimg/ramdisk.gz 8.拷貝該ramdisk.gz映像到tftpboot目錄下 cp rdimg/ramdisk.gz /tftpboot/ 9. 使用mkimage工具 mkimage -n "uboot.ramdisk.filesys" -A arm -O linux -T ramdisk -C gzip -d ramdisk.gz uboot.ramdisk.gz 參考:http://liaowb1234.blog.163.com/blog/static/771555472010027104534626/ http://www.cnblogs.com/sdphome/archive/2011/03/20/1989826.html 
 svn_externals:  src/android ###/frameworks/base/core/java/android src/com ###/frameworks/base/core/java/com src/com/android/internal/policy ###/frameworks/base/policy/src/com/android/internal/policy src/com/android/server ###/frameworks/base/services/java/com/android/server src/com/android/systemui/statusbar ###/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar src/android/telephony ###/frameworks/base/telephony/java/android/telephony src/com/android/internal/telephony ###/frameworks/base/telephony/java/com/android/internal/telephony src/android/opengl ###/frameworks/base/opengl/java/android/opengl src/javax/microedition/khronos ###/frameworks/base/opengl/java/javax/microedition/khronos src/android/drm ###/frameworks/base/media/java/android/drm src/android/media ###/frameworks/base/media/java/android/media src/android/graphics ###/frameworks/base/graphics/java/android/graphics src/android/renderscript ###/frameworks/base/graphics/java/android/renderscript src/com/android/internal/graphics ###/frameworks/base/graphics/java/com/android/internal/graphics svn_ignore: assets libs build_oms.xml .classpath .project bin 
 無(wú)論是在linux還是在Unix環(huán)境中,make都是一個(gè)非常重要的編譯命令。不管是自己進(jìn)行項(xiàng)目開(kāi)發(fā)還是安裝應(yīng)用軟件,我們都經(jīng)常要用到make或make install。利用make工具,我們可以將大型的開(kāi)發(fā)項(xiàng)目分解成為多個(gè)更易于管理的模塊,對(duì)于一個(gè)包括幾百個(gè)源文件的應(yīng)用程序,使用make和 makefile工具就可以簡(jiǎn)潔明快地理順各個(gè)源文件之間紛繁復(fù)雜的相互關(guān)系。而且如此多的源文件,如果每次都要鍵入gcc命令進(jìn)行編譯的話,那對(duì)程序員來(lái)說(shuō)簡(jiǎn)直就是一場(chǎng)災(zāi)難。而make工具則可自動(dòng)完成編譯工作,并且可以只對(duì)程序員在上次編譯后修改過(guò)的部分進(jìn)行編譯。因此,有效的利用make和
 makefile工具可以大大提高項(xiàng)目開(kāi)發(fā)的效率。同時(shí)掌握make和makefile之后,您也不會(huì)再面對(duì)著Linux下的應(yīng)用軟件手足無(wú)措了。  但令人遺憾的是,在許多講述linux應(yīng)用的書(shū)籍上都沒(méi)有詳細(xì)介紹這個(gè)功能強(qiáng)大但又非常復(fù)雜的編譯工具。在這里我就向大家詳細(xì)介紹一下make及其描述文件makefile。 Makefile文件 Make工具最主要也是最基本的功能就是通過(guò)makefile文件來(lái)描述源程序之間的相互關(guān)系并自動(dòng)維護(hù)編譯工作。而makefile 文件需要按照某種語(yǔ)法進(jìn)行編寫(xiě),文件中需要說(shuō)明如何編譯各個(gè)源文件并連接生成可執(zhí)行文件,并要求定義源文件之間的依賴關(guān)系。makefile 文件是許多編譯器--包括 Windows NT 下的編譯器--維護(hù)編譯信息的常用方法,只是在集成開(kāi)發(fā)環(huán)境中,用戶通過(guò)友好的界面修改 makefile 文件而已。 在 UNIX 系統(tǒng)中,習(xí)慣使用 Makefile 作為 makfile 文件。如果要使用其他文件作為 makefile,則可利用類似下面的 make 命令選項(xiàng)指定 makefile 文件: $ make -f Makefile.debug 例如,一個(gè)名為prog的程序由三個(gè)C源文件filea.c、fileb.c和filec.c以及庫(kù)文件LS編譯生成,這三個(gè)文件還分別包含自己的頭文件a.h 、b.h和c.h。通常情況下,C編譯器將會(huì)輸出三個(gè)目標(biāo)文件filea.o、fileb.o和filec.o。假設(shè)filea.c和fileb.c都要聲明用到一個(gè)名為defs的文件,但filec.c不用。即在filea.c和fileb.c里都有這樣的聲明: #include "defs" 那么下面的文檔就描述了這些文件之間的相互聯(lián)系: --------------------------------------------------------- #It is a example for describing makefile prog : filea.o fileb.o filec.o cc filea.o fileb.o filec.o -LS -o prog filea.o : filea.c a.h defs cc -c filea.c fileb.o : fileb.c b.h defs cc -c fileb.c filec.o : filec.c c.h cc -c filec.c ---------------------------------------------------------- 這個(gè)描述文檔就是一個(gè)簡(jiǎn)單的makefile文件。 從上面的例子注意到,第一個(gè)字符為 # 的行為注釋行。第一個(gè)非注釋行指定prog由三個(gè)目標(biāo)文件filea.o、fileb.o和filec.o鏈接生成。第三行描述了如何從prog所依賴的文件建立可執(zhí)行文件。接下來(lái)的4、6、8行分別指定三個(gè)目標(biāo)文件,以及它們所依賴的.c和.h文件以及defs文件。而5、7、9行則指定了如何從目標(biāo)所依賴的文件建立目標(biāo)。 當(dāng)filea.c或a.h文件在編譯之后又被修改,則 make 工具可自動(dòng)重新編譯filea.o,如果在前后兩次編譯之間,filea.C 和a.h 均沒(méi)有被修改,而且 test.o 還存在的話,就沒(méi)有必要重新編譯。這種依賴關(guān)系在多源文件的程序編譯中尤其重要。通過(guò)這種依賴關(guān)系的定義,make 工具可避免許多不必要的編譯工作。當(dāng)然,利用 Shell 腳本也可以達(dá)到自動(dòng)編譯的效果,但是,Shell 腳本將全部編譯任何源文件,包括哪些不必要重新編譯的源文件,而 make 工具則可根據(jù)目標(biāo)上一次編譯的時(shí)間和目標(biāo)所依賴的源文件的更新時(shí)間而自動(dòng)判斷應(yīng)當(dāng)編譯哪個(gè)源文件。 Makefile文件作為一種描述文檔一般需要包含以下內(nèi)容: ◆ 宏定義 ◆ 源文件之間的相互依賴關(guān)系 ◆ 可執(zhí)行的命令 Makefile中允許使用簡(jiǎn)單的宏指代源文件及其相關(guān)編譯信息,在linux中也稱宏為變量。在引用宏時(shí)只需在變量前加$符號(hào),但值得注意的是,如果變量名的長(zhǎng)度超過(guò)一個(gè)字符,在引用時(shí)就必須加圓括號(hào)()。 下面都是有效的宏引用: $(CFLAGS) $2 $Z $(Z) 其中最后兩個(gè)引用是完全一致的。 需要注意的是一些宏的預(yù)定義變量,在Unix系統(tǒng)中,$*、$@、$?和$<四個(gè)特殊宏的值在執(zhí)行命令的過(guò)程中會(huì)發(fā)生相應(yīng)的變化,而在GNU make中則定義了更多的預(yù)定義變量。關(guān)于預(yù)定義變量的詳細(xì)內(nèi)容, 宏定義的使用可以使我們脫離那些冗長(zhǎng)乏味的編譯選項(xiàng),為編寫(xiě)makefile文件帶來(lái)很大的方便。 --------------------------------------------------------- # Define a macro for the object files OBJECTS= filea.o fileb.o filec.o # Define a macro for the library file LIBES= -LS # use macros rewrite makefile prog: $(OBJECTS) cc $(OBJECTS) $(LIBES) -o prog …… --------------------------------------------------------- 此時(shí)如果執(zhí)行不帶參數(shù)的make命令,將連接三個(gè)目標(biāo)文件和庫(kù)文件LS;但是如果在make命令后帶有新的宏定義: make "LIBES= -LL -LS" 則命令行后面的宏定義將覆蓋makefile文件中的宏定義。若LL也是庫(kù)文件,此時(shí)make命令將連接三個(gè)目標(biāo)文件以及兩個(gè)庫(kù)文件LS和LL。 在Unix系統(tǒng)中沒(méi)有對(duì)常量NULL作出明確的定義,因此我們要定義NULL字符串時(shí)要使用下述宏定義: STRINGNAME= Make命令 在make命令后不僅可以出現(xiàn)宏定義,還可以跟其他命令行參數(shù),這些參數(shù)指定了需要編譯的目標(biāo)文件。其標(biāo)準(zhǔn)形式為: target1 [target2 …]:[:][dependent1 …][;commands][#…] [(tab) commands][#…] 方括號(hào)中間的部分表示可選項(xiàng)。Targets和dependents當(dāng)中可以包含字符、數(shù)字、句點(diǎn)和"/"符號(hào)。除了引用,commands中不能含有"#",也不允許換行。 在通常的情況下命令行參數(shù)中只含有一個(gè)":",此時(shí)command序列通常和makefile文件中某些定義文件間依賴關(guān)系的描述行有關(guān)。如果與目標(biāo)相關(guān)連的那些描述行指定了相關(guān)的command序列,那么就執(zhí)行這些相關(guān)的command命令,即使在分號(hào)和(tab)后面的aommand字段甚至有可能是NULL。如果那些與目標(biāo)相關(guān)連的行沒(méi)有指定command,那么將調(diào)用系統(tǒng)默認(rèn)的目標(biāo)文件生成規(guī)則。 如果命令行參數(shù)中含有兩個(gè)冒號(hào)"::",則此時(shí)的command序列也許會(huì)和makefile中所有描述文件依賴關(guān)系的行有關(guān)。此時(shí)將執(zhí)行那些與目標(biāo)相關(guān)連的描述行所指向的相關(guān)命令。同時(shí)還將執(zhí)行build-in規(guī)則。 如果在執(zhí)行command命令時(shí)返回了一個(gè)非"0"的出錯(cuò)信號(hào),例如makefile文件中出現(xiàn)了錯(cuò)誤的目標(biāo)文件名或者出現(xiàn)了以連字符打頭的命令字符串,make操作一般會(huì)就此終止,但如果make后帶有"-i"參數(shù),則make將忽略此類出錯(cuò)信號(hào)。 Make命本身可帶有四種參數(shù):標(biāo)志、宏定義、描述文件名和目標(biāo)文件名。其標(biāo)準(zhǔn)形式為: Make [flags] [macro definitions] [targets] Unix系統(tǒng)下標(biāo)志位flags選項(xiàng)及其含義為: -f file 指定file文件為描述文件,如果file參數(shù)為"-"符,那么描述文件指向標(biāo)準(zhǔn)輸入。如果沒(méi)有"-f"參數(shù),則系統(tǒng)將默認(rèn)當(dāng)前目錄下名為 makefile或者名為Makefile的文件為描述文件。在linux中, GNU make 工具在當(dāng)前工作目錄中按照GNUmakefile、makefile、Makefile的順序搜索 makefile文件。 -i 忽略命令執(zhí)行返回的出錯(cuò)信息。 -s 沉默模式,在執(zhí)行之前不輸出相應(yīng)的命令行信息。 -r 禁止使用build-in規(guī)則。 -n 非執(zhí)行模式,輸出所有執(zhí)行命令,但并不執(zhí)行。 -t 更新目標(biāo)文件。 -q make操作將根據(jù)目標(biāo)文件是否已經(jīng)更新返回"0"或非"0"的狀態(tài)信息。 -p 輸出所有宏定義和目標(biāo)文件描述。 -d Debug模式,輸出有關(guān)文件和檢測(cè)時(shí)間的詳細(xì)信息。 linux下make標(biāo)志位的常用選項(xiàng)與Unix系統(tǒng)中稍有不同,下面我們只列出了不同部分: -c dir 在讀取 makefile 之前改變到指定的目錄dir。 -I dir 當(dāng)包含其他 makefile文件時(shí),利用該選項(xiàng)指定搜索目錄。 -h help文擋,顯示所有的make選項(xiàng)。 -w 在處理 makefile 之前和之后,都顯示工作目錄。 通過(guò)命令行參數(shù)中的target ,可指定make要編譯的目標(biāo),并且允許同時(shí)定義編譯多個(gè)目標(biāo),操作時(shí)按照從左向右的順序依次編譯target選項(xiàng)中指定的目標(biāo)文件。如果命令行中沒(méi)有指定目標(biāo),則系統(tǒng)默認(rèn)target指向描述文件中第一個(gè)目標(biāo)文件。 通常,makefile 中還定義有 clean 目標(biāo),可用來(lái)清除編譯過(guò)程中的中間文件,例如: clean: rm -f *.o 運(yùn)行 make clean 時(shí),將執(zhí)行 rm -f *.o 命令,最終刪除所有編譯過(guò)程中產(chǎn)生的所有中間文件。 隱含規(guī)則 在make 工具中包含有一些內(nèi)置的或隱含的規(guī)則,這些規(guī)則定義了如何從不同的依賴文件建立特定類型的目標(biāo)。Unix系統(tǒng)通常支持一種基于文件擴(kuò)展名即文件名后綴的隱含規(guī)則。這種后綴規(guī)則定義了如何將一個(gè)具有特定文件名后綴的文件(例如.c文件),轉(zhuǎn)換成為具有另一種文件名后綴的文件(例如.o文件): .c:.o $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $< 系統(tǒng)中默認(rèn)的常用文件擴(kuò)展名及其含義為: .o 目標(biāo)文件 .c C源文件 .f FORTRAN源文件 .s 匯編源文件 .y Yacc-C源語(yǔ)法 .l Lex源語(yǔ)法 在早期的Unix系統(tǒng)系統(tǒng)中還支持Yacc-C源語(yǔ)法和Lex源語(yǔ)法。在編譯過(guò)程中,系統(tǒng)會(huì)首先在makefile文件中尋找與目標(biāo)文件相關(guān)的.C文件,如果還有與之相依賴的.y和.l文件,則首先將其轉(zhuǎn)換為.c文件后再編譯生成相應(yīng)的.o文件;如果沒(méi)有與目標(biāo)相關(guān)的.c文件而只有相關(guān)的.y文件,則系統(tǒng)將直接編譯.y文件。 而GNU make 除了支持后綴規(guī)則外還支持另一種類型的隱含規(guī)則--模式規(guī)則。這種規(guī)則更加通用,因?yàn)榭梢岳媚J揭?guī)則定義更加復(fù)雜的依賴性規(guī)則。模式規(guī)則看起來(lái)非常類似于正則規(guī)則,但在目標(biāo)名稱的前面多了一個(gè) % 號(hào),同時(shí)可用來(lái)定義目標(biāo)和依賴文件之間的關(guān)系,例如下面的模式規(guī)則定義了如何將任意一個(gè) file.c 文件轉(zhuǎn)換為 file.o 文件: %.c:%.o $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $< #EXAMPLE# 下面將給出一個(gè)較為全面的示例來(lái)對(duì)makefile文件和make命令的執(zhí)行進(jìn)行進(jìn)一步的說(shuō)明,其中make命令不僅涉及到了C源文件還包括了Yacc 語(yǔ)法。本例選自"Unix Programmer's Manual 7th Edition, Volume 2A" Page 283-284 下面是描述文件的具體內(nèi)容: --------------------------------------------------------- #Description file for the Make command #Send to print P=und -3 | opr -r2 #The source files that are needed by object files FILES= Makefile version.c defs main.c donamc.c misc.c file.c dosys.c gram.y lex.c gcos.c #The definitions of object files OBJECTS= vesion.o main.o donamc.o misc.o file.o dosys.o gram.o LIBES= -LS LINT= lnit -p CFLAGS= -O make: $(OBJECTS) cc $(CFLAGS) $(OBJECTS) $(LIBES) -o make size make $(OBJECTS): defs gram.o: lex.c cleanup: -rm *.o gram.c install: @size make /usr/bin/make cp make /usr/bin/make ; rm make #print recently changed files print: $(FILES) pr $? | $P touch print test: make -dp | grep -v TIME>1zap /usr/bin/make -dp | grep -v TIME>2zap diff 1zap 2zap rm 1zap 2zap lint: dosys.c donamc.c file.c main.c misc.c version.c gram.c $(LINT) dosys.c donamc.c file.c main.c misc.c version.c gram.c rm gram.c arch: ar uv /sys/source/s2/make.a $(FILES) ---------------------------------------------------------- 通常在描述文件中應(yīng)象上面一樣定義要求輸出將要執(zhí)行的命令。在執(zhí)行了make命令之后,輸出結(jié)果為: $ make cc -c version.c cc -c main.c cc -c donamc.c cc -c misc.c cc -c file.c cc -c dosys.c yacc gram.y mv y.tab.c gram.c cc -c gram.c cc version.o main.o donamc.o misc.o file.o dosys.o gram.o -LS -o make 13188+3348+3044=19580b=046174b 最后的數(shù)字信息是執(zhí)行"@size make"命令的輸出結(jié)果。之所以只有輸出結(jié)果而沒(méi)有相應(yīng)的命令行,是因?yàn)?@size make"命令以"@"起始,這個(gè)符號(hào)禁止打印輸出它所在的命令行。 描述文件中的最后幾條命令行在維護(hù)編譯信息方面非常有用。其中"print"命令行的作用是打印輸出在執(zhí)行過(guò)上次"make print"命令后所有改動(dòng)過(guò)的文件名稱。系統(tǒng)使用一個(gè)名為print的0字節(jié)文件來(lái)確定執(zhí)行print命令的具體時(shí)間,而宏$?則指向那些在print 文件改動(dòng)過(guò)之后進(jìn)行修改的文件的文件名。如果想要指定執(zhí)行print命令后,將輸出結(jié)果送入某個(gè)指定的文件,那么就可修改P的宏定義: make print "P= cat>zap" 在linux中大多數(shù)軟件提供的是源代碼,而不是現(xiàn)成的可執(zhí)行文件,這就要求用戶根據(jù)自己系統(tǒng)的實(shí)際情況和自身的需要來(lái)配置、編譯源程序后,軟件才能使用。只有掌握了make工具,才能讓我們真正享受到到Linux這個(gè)自由軟件世界的帶給我們無(wú)窮樂(lè)趣。 另一篇,http://wiki./%E8%B7%9F%E6%88%91%E4%B8%80%E8%B5%B7%E5%86%99Makefile 
 build/envsetup.sh腳本分析  在編譯源代碼之前通常需要在android源代碼頂層目錄執(zhí)行 . ./build/envsetup.sh 目的是為了使用 腳本 envsetup.sh 里面定義了一些函數(shù): function help() function get_abs_build_var() function get_build_var() function check_product() function check_variant() function setpaths() function printconfig() function set_stuff_for_environment() function set_sequence_number() function settitle() function choosetype() function chooseproduct() function choosevariant() function tapas() function choosecombo() function print_lunch_menu() function lunch() function gettop function m() function findmakefile() function mm() function mmm() function croot() function pid() function gdbclient() function jgrep() function cgrep() function resgrep() function getprebuilt function tracedmdump() function runhat() function getbugreports() function startviewserver() function stopviewserver() function isviewserverstarted() function smoketest() function runtest() function runtest_py() function godir () choosecombo 命令分析: function choosecombo() { choosesim $1 echo echo choosetype $2 echo echo chooseproduct $3 echo echo choosevariant $4 echo set_stuff_for_environment printconfig } 會(huì)依次進(jìn)行如下選擇: Build for the simulator or the device? 1. Device 2. Simulator Which would you like? [1] Build type c Build type choices are: 1. release 2. debug Which would you like? [1] Product choices are: 1. emulator 2. generic 3. sim 4. littleton You can also type the name of a product if you know it. Which would you like? [littleton] Variant choices are: 1. user 2. userdebug 3. eng Which would you like? [eng] user 默認(rèn)選擇以后會(huì)出現(xiàn): TARGET_PRODUCT=littleton TARGET_BUILD_VARIANT=user TARGET_SIMULATOR=false TARGET_BUILD_TYPE=release TARGET_ARCH=arm HOST_ARCH=x86 HOST_OS=linux HOST_BUILD_TYPE=release BUILD_ID= ========== function chooseproduct()函數(shù)分析: choices=(`/bin/ls build/target/board/*/BoardConfig.mk vendor/*/*/BoardConfig.mk 2> /dev/null`) 讀取 build/target/board/* 目錄下的板配置文件:BoardConfig.mk 讀取 vendor/*/*/目錄下的板配置文件:BoardConfig.mk choices 的值為: build/target/board/emulator/BoardConfig.mk build/target/board/generic/BoardConfig.mk build/target/board/sim/BoardConfig.mk vendor/marvell/littleton/BoardConfig.mk 經(jīng)過(guò): for choice in ${choices[@]} do # The product name is the name of the directory containing # the makefile we found, above. prodlist=(${prodlist[@]} `dirname ${choice} | xargs basename`) done 的處理,prodlist的值為: emulator generic sim littleton 所以選擇菜單為: Product choices are: 1. emulator 2. generic 3. sim 4. littleton 如果選擇 4,那么 TARGET_PRODUCT 被賦值為: littleton。 board_config_mk := \ $(strip $(wildcard \ $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)/BoardConfig.mk \ vendor/*/$(TARGET_DEVICE)/BoardConfig.mk \ )) 怎樣添加一個(gè)模塊 LOCAL_PATH:= $(call my-dir) #編譯靜態(tài)庫(kù) include $(CLEAR_VARS) LOCAL_MODULE = libhellos LOCAL_CFLAGS = $(L_CFLAGS) LOCAL_SRC_FILES = hellos.c LOCAL_C_INCLUDES = $(INCLUDES) LOCAL_SHARED_LIBRARIES := libcutils LOCAL_COPY_HEADERS_TO := libhellos LOCAL_COPY_HEADERS := hellos.h include $(BUILD_STATIC_LIBRARY) #編譯動(dòng)態(tài)庫(kù) include $(CLEAR_VARS) LOCAL_MODULE = libhellod LOCAL_CFLAGS = $(L_CFLAGS) LOCAL_SRC_FILES = hellod.c LOCAL_C_INCLUDES = $(INCLUDES) LOCAL_SHARED_LIBRARIES := libcutils LOCAL_COPY_HEADERS_TO := libhellod LOCAL_COPY_HEADERS := hellod.h include $(BUILD_SHARED_LIBRARY) BUILD_TEST=true ifeq ($(BUILD_TEST),true) #使用靜態(tài)庫(kù) include $(CLEAR_VARS) LOCAL_MODULE := hellos LOCAL_STATIC_LIBRARIES := libhellos LOCAL_SHARED_LIBRARIES := LOCAL_LDLIBS += -ldl LOCAL_CFLAGS := $(L_CFLAGS) LOCAL_SRC_FILES := mains.c LOCAL_C_INCLUDES := $(INCLUDES) include $(BUILD_EXECUTABLE) #使用動(dòng)態(tài)庫(kù) include $(CLEAR_VARS) LOCAL_MODULE := hellod LOCAL_MODULE_TAGS := debug LOCAL_SHARED_LIBRARIES := libc libcutils libhellod LOCAL_LDLIBS += -ldl LOCAL_CFLAGS := $(L_CFLAGS) LOCAL_SRC_FILES := maind.c LOCAL_C_INCLUDES := $(INCLUDES) include $(BUILD_EXECUTABLE) endif # ifeq ($(WPA_BUILD_SUPPLICANT),true) ######################## #local_target_dir := $(TARGET_OUT)/etc/wifi #include $(CLEAR_VARS) #LOCAL_MODULE := wpa_supplicant.conf #LOCAL_MODULE_TAGS := user #LOCAL_MODULE_CLASS := ETC #LOCAL_MODULE_PATH := $(local_target_dir) #LOCAL_SRC_FILES := $(LOCAL_MODULE) #include $(BUILD_PREBUILT) ######################## 系統(tǒng)變量解析 LOCAL_MODULE - 編譯的目標(biāo)對(duì)象 LOCAL_SRC_FILES - 編譯的源文件 LOCAL_C_INCLUDES - 需要包含的頭文件目錄 LOCAL_SHARED_LIBRARIES - 鏈接時(shí)需要的外部庫(kù) LOCAL_PRELINK_MODULE - 是否需要prelink處理 BUILD_SHARED_LIBRARY - 指明要編譯成動(dòng)態(tài)庫(kù) LOCAL_PATH - 編譯時(shí)的目錄 $(call 目錄,目錄….) 目錄引入操作符 如該目錄下有個(gè)文件夾名稱 src,則可以這樣寫(xiě) $(call src),那么就會(huì)得到 src 目錄的完整路徑 include $(CLEAR_VARS) -清除之前的一些系統(tǒng)變量 CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mk 在 build/core/config.mk 定義 CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mk 通過(guò)include 包含自定義的.mk文件(即是自定義編譯規(guī)則)或是引用系統(tǒng)其他的.mk文件(系統(tǒng)定義的編譯規(guī)則)。 LOCAL_SRC_FILES - 編譯的源文件 可以是.c, .cpp, .java, .S(匯編文件)或是.aidl等格式 不同的文件用空格隔開(kāi)。如果編譯目錄子目錄,采用相對(duì)路徑,如子目錄/文件名。也可以通過(guò)$(call 目錄),指明編譯某目錄 下所有.c/.cpp/.java/.S/ .aidl文件.追加文件 LOCAL_SRC_FILES += 文件 LOCAL_C_INCLUDES - 需要包含的頭文件目錄 可以是系統(tǒng)定義路徑,也可以是相對(duì)路徑. 如該編譯目錄下有個(gè)include目錄,寫(xiě)法是include/*.h LOCAL_SHARED_LIBRARIES - 鏈接時(shí)需要的外部共享庫(kù) LOCAL_STATIC_LIBRARIES - 鏈接時(shí)需要的外部外部靜態(tài) LOCAL_JAVA_LIBRARIES 加入jar包 LOCAL_MODULE - 編譯的目標(biāo)對(duì)象 module 是指系統(tǒng)的 native code,通常針對(duì)c,c++代碼 ./system/core/sh/Android.mk:32:LOCAL_MODULE:= sh ./system/core/libcutils/Android.mk:71:LOCAL_MODULE := libcutils ./system/core/cpio/Android.mk:9:LOCAL_MODULE := mkbootfs ./system/core/mkbootimg/Android.mk:8:LOCAL_MODULE := mkbootimg ./system/core/toolbox/Android.mk:61:LOCAL_MODULE:= toolbox ./system/core/logcat/Android.mk:10:LOCAL_MODULE:= logcat ./system/core/adb/Android.mk:65:LOCAL_MODULE := adb ./system/core/adb/Android.mk:125:LOCAL_MODULE := adbd ./system/core/init/Android.mk:20:LOCAL_MODULE:= init ./system/core/vold/Android.mk:24:LOCAL_MODULE:= vold ./system/core/mountd/Android.mk:13:LOCAL_MODULE:= mountd LOCAL_PACKAGE_NAME Java 應(yīng)用程序的名字用該變量定義 ./packages/apps/Music/Android.mk:9:LOCAL_PACKAGE_NAME := Music ./packages/apps/Browser/Android.mk:14:LOCAL_PACKAGE_NAME := Browser ./packages/apps/Settings/Android.mk:8:LOCAL_PACKAGE_NAME := Settings ./packages/apps/Stk/Android.mk:10:LOCAL_PACKAGE_NAME := Stk ./packages/apps/Contacts/Android.mk:10:LOCAL_PACKAGE_NAME := Contacts ./packages/apps/Mms/Android.mk:8:LOCAL_PACKAGE_NAME := Mms ./packages/apps/Camera/Android.mk:8:LOCAL_PACKAGE_NAME := Camera ./packages/apps/Phone/Android.mk:11:LOCAL_PACKAGE_NAME := Phone ./packages/apps/VoiceDialer/Android.mk:8:LOCAL_PACKAGE_NAME := VoiceDialer BUILD_SHARED_LIBRARY - 指明要編譯成動(dòng)態(tài)庫(kù)。 編譯的目標(biāo),用include 操作符 UILD_STATIC_LIBRARY來(lái)指明要編譯成靜態(tài)庫(kù)。 如果是java文件的話,會(huì)用到系統(tǒng)的編譯腳本host_java_library.mk,用BUILD_PACKAGE來(lái)指明。三個(gè)編譯 ------------------- include $(BUILD_STATIC_LIBRARY) BUILD_STATIC_LIBRARY:= $(BUILD_SYSTEM)/static_library.mk ------------------- include $(BUILD_SHARED_LIBRARY) ./build/core/config.mk:50:BUILD_SHARED_LIBRARY:= $(BUILD_SYSTEM)/shared_library.mk ------------------- include $(BUILD_HOST_SHARED_LIBRARY) BUILD_HOST_SHARED_LIBRARY:= $(BUILD_SYSTEM)/host_shared_library.mk ------------------- include $(BUILD_EXECUTABLE) build/core/config.mk:51:BUILD_EXECUTABLE:= $(BUILD_SYSTEM)/executable.mk ------------------- include $(BUILD_HOST_EXECUTABLE) ./build/core/config.mk:53:BUILD_HOST_EXECUTABLE:= $(BUILD_SYSTEM)/host_executable.mk ------------------- BUILD_HOST_JAVA_LIBRARY:= $(BUILD_SYSTEM)/host_java_library.mk ------------------- BUILD_JAVA_LIBRARY ./build/core/config.mk:58:BUILD_JAVA_LIBRARY:= $(BUILD_SYSTEM)/java_library.mk ------------------ BUILD_STATIC_JAVA_LIBRARY 編譯靜態(tài)JAVA庫(kù) ./build/core/config.mk:59:BUILD_STATIC_JAVA_LIBRARY:= $(BUILD_SYSTEM)/static_java_library.mk ------------------ BUILD_HOST_JAVA_LIBRARY 編譯本機(jī)用的JAVA庫(kù) ./build/core/config.mk:60:BUILD_HOST_JAVA_LIBRARY:= $(BUILD_SYSTEM)/host_java_library.mk ------------------ BUILD_HOST_STATIC_LIBRARY:= $(BUILD_SYSTEM)/host_static_library.mk BUILD_HOST_SHARED_LIBRARY:= $(BUILD_SYSTEM)/host_shared_library.mk BUILD_STATIC_LIBRARY:= $(BUILD_SYSTEM)/static_library.mk BUILD_RAW_STATIC_LIBRARY := $(BUILD_SYSTEM)/raw_static_library.mk BUILD_SHARED_LIBRARY:= $(BUILD_SYSTEM)/shared_library.mk BUILD_EXECUTABLE:= $(BUILD_SYSTEM)/executable.mk BUILD_RAW_EXECUTABLE:= $(BUILD_SYSTEM)/raw_executable.mk BUILD_HOST_EXECUTABLE:= $(BUILD_SYSTEM)/host_executable.mk BUILD_PACKAGE:= $(BUILD_SYSTEM)/package.mk BUILD_HOST_PREBUILT:= $(BUILD_SYSTEM)/host_prebuilt.mk BUILD_PREBUILT:= $(BUILD_SYSTEM)/prebuilt.mk BUILD_MULTI_PREBUILT:= $(BUILD_SYSTEM)/multi_prebuilt.mk BUILD_JAVA_LIBRARY:= $(BUILD_SYSTEM)/java_library.mk BUILD_STATIC_JAVA_LIBRARY:= $(BUILD_SYSTEM)/static_java_library.mk BUILD_HOST_JAVA_LIBRARY:= $(BUILD_SYSTEM)/host_java_library.mk BUILD_DROIDDOC:= $(BUILD_SYSTEM)/droiddoc.mk BUILD_COPY_HEADERS := $(BUILD_SYSTEM)/copy_headers.mk BUILD_KEY_CHAR_MAP := $(BUILD_SYSTEM)/key_char_map.mk ============ LOCAL_PRELINK_MODULE Prelink利用事先鏈接代替運(yùn)行時(shí)鏈接的方法來(lái)加速共享庫(kù)的加載,它不僅可以加快起動(dòng)速度,還可以減少部分內(nèi)存開(kāi)銷, 是各種Linux架構(gòu)上用于減少程序加載時(shí)間、縮短系統(tǒng)啟動(dòng)時(shí)間和加快應(yīng)用程序啟動(dòng)的很受歡迎的一個(gè)工具。程序運(yùn)行時(shí)的 動(dòng)態(tài)鏈接尤其是重定位(relocation)的開(kāi)銷對(duì)于大型系統(tǒng)來(lái)說(shuō)是很大的。 動(dòng)態(tài)鏈接和加載的過(guò)程開(kāi)銷很大,并且在大多數(shù)的系統(tǒng)上, 函數(shù)庫(kù)并不會(huì)常常被更動(dòng), 每次程序被執(zhí)行時(shí)所進(jìn)行的鏈接 動(dòng)作都是完全相同的,對(duì)于嵌入式系統(tǒng)來(lái)說(shuō)尤其如此。因此,這一過(guò)程可以改在運(yùn)行時(shí)之前就可以預(yù)先處理好,即花一些時(shí)間 利用Prelink工具對(duì)動(dòng)態(tài)共享庫(kù)和可執(zhí)行文件進(jìn)行處理,修改這些二進(jìn)制文件并加入相應(yīng)的重定位等信息,節(jié)約了本來(lái)在程序 啟動(dòng)時(shí)的比較耗時(shí)的查詢函數(shù)地址等工作,這樣可以減少程序啟動(dòng)的時(shí)間,同時(shí)也減少了內(nèi)存的耗用。 Prelink的這種做法當(dāng)然也有代價(jià):每次更新動(dòng)態(tài)共享庫(kù)時(shí),相關(guān)的可執(zhí)行文件都需要重新執(zhí)行一遍Prelink才能保 證有效,因?yàn)樾碌墓蚕韼?kù)中的符號(hào)信息、地址等很可能與原來(lái)的已經(jīng)不同了,這就是為什么 android framework代碼一改動(dòng), 這時(shí)候就會(huì)導(dǎo)致相關(guān)的應(yīng)用程序重新被編譯。 這種代價(jià)對(duì)于嵌入式系統(tǒng)的開(kāi)發(fā)者來(lái)說(shuō)可能稍微帶來(lái)一些復(fù)雜度,不過(guò)好在對(duì)用戶來(lái)說(shuō)幾乎是可以忽略的。 -------------------- 變量設(shè)置為false那么將不做prelink操作 LOCAL_PRELINK_MODULE := false 默認(rèn)是需要prlink的,同時(shí)需要在 build/core/prelink-linux-arm.map 中加入 libhellod.so 0x96000000 這個(gè)map文件好像是制定動(dòng)態(tài)庫(kù)的地址的,在前面注釋上面有一些地址范圍的信息,注意庫(kù)與庫(kù)之間的間隔數(shù), 如果指定不好的話編譯的時(shí)候會(huì)提示說(shuō)地址空間沖突的問(wèn)題。另外,注意排序,這里要把數(shù)大的放到前面去, 按照大小降序排序。 解析 LOCAL_PRELINK_MODULE 變量 build/core/dynamic_binary.mk:94:ifeq ($(LOCAL_PRELINK_MODULE),true) ifeq ($(LOCAL_PRELINK_MODULE),true) $(prelink_output): $(prelink_input) $(TARGET_PRELINKER_MAP) $(APRIORI) $(transform-to-prelinked) transform-to-prelinked定義: ./build/core/definitions.mk:1002:define transform-to-prelinked define transform-to-prelinked @mkdir -p $(dir $@) @echo "target Prelink: $(PRIVATE_MODULE) ($@)" $(hide) $(APRIORI) \ --prelinkmap $(TARGET_PRELINKER_MAP) \ --locals-only \ --quiet \ $/build/tools/apriori” 參考文檔: 動(dòng)態(tài)庫(kù)優(yōu)化——Prelink(預(yù)連接)技術(shù) http://www./article/09-04/71629s.html =============== LOCAL_ARM_MODE := arm 目前Android大部分都是基于Arm處理器的,Arm指令用兩種模式Thumb(每條指令兩個(gè)字節(jié))和arm指令(每條指令四個(gè)字節(jié)) LOCAL_CFLAGS += -O3 -fstrict-aliasing -fprefetch-loop-arrays 通過(guò)設(shè)定編譯器操作,優(yōu)化級(jí)別,-O0表示沒(méi)有優(yōu)化,-O1為缺省值,-O3優(yōu)化級(jí)別最高 LOCAL_CFLAGS += -W -Wall LOCAL_CFLAGS += -fPIC -DPIC LOCAL_CFLAGS += -O2 -g -DADB_HOST=1 -Wall -Wno-unused-parameter LOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE -DSH_HISTORY LOCAL_CFLAGS += -DUSEOVERLAY2 根據(jù)條件選擇相應(yīng)的編譯參數(shù) ifeq ($(TARGET_ARCH),arm) LOCAL_CFLAGS += -DANDROID_GADGET=1 LOCAL_CFLAGS := $(PV_CFLAGS) endif ifeq ($(TARGET_BUILD_TYPE),release) LOCAL_CFLAGS += -O2 endif LOCAL_LDLIBS := -lpthread LOCAL_LDLIBS += -ldl ifdef USE_MARVELL_MVED LOCAL_WHOLE_STATIC_LIBRARIES += lib_il_mpeg4aspdecmved_wmmx2lnx lib_il_h264decmved_wmmx2lnx LOCAL_SHARED_LIBRARIES += libMrvlMVED else LOCAL_WHOLE_STATIC_LIBRARIES += lib_il_h264dec_wmmx2lnx lib_il_mpeg4aspdec_wmmx2lnx endif ==================== 其他一些變量和腳本: HOST_JNILIB_SUFFIX LOCAL_MODULE_SUFFIX LOCAL_MODULE_SUFFIX := $(HOST_JNILIB_SUFFIX) HOST_GLOBAL_LDFLAGS TARGET_GLOBAL_LDFLAGS PRIVATE_LDFLAGS LOCAL_LDLIBS LOCAL_C_INCLUDES LOCAL_STATIC_LIBRARIES LOCAL_STATIC_LIBRARIES += codecJPDec_WMMX2LNX miscGen_WMMX2LNX LOCAL_SHARED_LIBRARIES LOCAL_SHARED_LIBRARIES += libMrvlIPP LOCAL_SHARED_LIBRARIES += $(common_SHARED_LIBRARIES) LOCAL_SHARED_LIBRARIES += libMrvlIPP LOCAL_SHARED_LIBRARIES += libdl ifeq ($(TARGET_PRODUCT),littleton) LOCAL_C_INCLUDES += vendor/marvell/littleton/m2d \ LOCAL_SHARED_LIBRARIES += libOmxCore endif vendor/marvell/littleton/littleton.mk:27:PRODUCT_NAME := littleton vendor/marvell/littleton/littleton.mk:28:PRODUCT_DEVICE := littleton vendor/marvell/littleton/AndroidProducts.mk:13: $(LOCAL_DIR)/littleton.mk vendor/sample/products/sample_addon.mk:40:PRODUCT_NAME := sample_addon vendor/htc/dream-open/htc_dream.mk:6:PRODUCT_NAME := htc_dream ./vendor/htc/dream-open/htc_dream.mk:7:PRODUCT_DEVICE := dream-open ./vendor/htc/dream-open/AndroidProducts.mk:3: $(LOCAL_DIR)/htc_dream.mk build/target/product/generic.mk:26:PRODUCT_NAME := generic build/target/product/generic_with_google.mk:20:PRODUCT_NAME := generic_with_google build/target/product/min_dev.mk:6:PRODUCT_NAME := min_dev build/target/product/core.mk:2:PRODUCT_NAME := build/target/product/sim.mk:7:PRODUCT_NAME := sim build/target/product/sdk.mk:37:PRODUCT_NAME := sdk build/tools/buildinfo.sh:20:echo "ro.product.name=$PRODUCT_NAME" lunch sample_addon-eng | 
|  |