Android系统在超级终端下必会的命令大全(adb shell命令大全)
生活随笔
收集整理的這篇文章主要介紹了
Android系统在超级终端下必会的命令大全(adb shell命令大全)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
1. 顯示系統(tǒng)中全部Android平臺:
android list targets
2. 顯示系統(tǒng)中全部AVD(模擬器):
android list avd
3. 創(chuàng)建AVD(模擬器):
android create avd --name 名稱 --target 平臺編號
4. 啟動模擬器:
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. 啟動DDMS:
ddms
9. 顯示當(dāng)前運(yùn)行的全部模擬器:
adb devices
10. 對某一模擬器執(zhí)行命令:
abd -s 模擬器編號 命令
11. 安裝應(yīng)用程序:
adb install -r 應(yīng)用程序.apk
12. 獲取模擬器中的文件:
adb pull <remote> <local>
13. 向模擬器中寫文件:
adb push <local> <remote>
14. 進(jìn)入模擬器的shell模式:
adb shell
15. 啟動SDK,文檔,實例下載管理器:
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后面跟的命令主要來自:
源碼\system\core\toolbox目錄和源碼\frameworks\base\cmds目錄。
20. 刪除系統(tǒng)應(yīng)用:
adb remount (重新掛載系統(tǒng)分區(qū),使系統(tǒng)分區(qū)重新可寫)。
adb shell
cd system/app
rm *.apk
21. 獲取管理員權(quán)限:
adb root
22. 啟動Activity:
adb shell am start -n 包名/包名+類名(-n 類名,-a action,-d date,-m MIME-TYPE,-c category,-e 擴(kuò)展數(shù)據(jù),等)。
23、發(fā)布端口:
你可以設(shè)置任意的端口號,做為主機(jī)向模擬器或設(shè)備的請求端口。如:
adb forward tcp:5555 tcp:8000
24、復(fù)制文件:
你可向一個設(shè)備或從一個設(shè)備中復(fù)制文件,
復(fù)制一個文件或目錄到設(shè)備或模擬器上:
adb push <source> <destination></destination></source>
如:adb push test.txt /tmp/test.txt
從設(shè)備或模擬器上復(fù)制一個文件或目錄:
adb pull <source> <destination></destination></source>
如:adb pull /addroid/lib/libwebcore.so .
25、搜索模擬器/設(shè)備的實例:
取得當(dāng)前運(yùn)行的模擬器/設(shè)備的實例的列表及每個實例的狀態(tài):
adb devices
26、查看bug報告:
adb bugreport
27、記錄無線通訊日志:
一般來說,無線通訊的日志非常多,在運(yùn)行時沒必要去記錄,但我們還是可以通過命令,設(shè)置記錄:
adb shell
logcat -b radio
28、獲取設(shè)備的ID和序列號:
adb get-product
adb get-serialno
29、訪問數(shù)據(jù)庫SQLite3
adb shell
sqlite3
busybox
BusyBox 是標(biāo)準(zhǔn) Linux 工具的一個單個可執(zhí)行實現(xiàn)。BusyBox 包含了一些簡單的工具,例如 cat 和 echo,還包含了一些更大、更復(fù)雜的工具,例如 grep、find、mount 以及 telnet。有些人將 BusyBox 稱為 Linux 工具里的瑞士軍刀.簡單的說BusyBox就好像是個大工具箱,它集成壓縮了 Linux 的許多工具和命令。
1、 BusyBox 的誕生
BusyBox 最初是由 Bruce Perens 在 1996 年為 Debian GNU/Linux 安裝盤編寫的。其目標(biāo)是在一張軟盤上創(chuàng)建一個可引導(dǎo)的 GNU/Linux 系統(tǒng),這可以用作安裝盤和急救盤。
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)行這三個鏈接:
#./ls
#./rm
#./mkdir
就可以分別完成了ls rm 和mkdir命令的功能.雖然他們都指向同一個可執(zhí)行程序busybox,但是只要鏈接名不同,完成的功能就不同,很多l(xiāng)inux網(wǎng)站都提供busybox的源代碼下載。
3、配置busybox
busybox的配置程序和linux內(nèi)核菜單配置方式簡直一模一樣.熟悉用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的功能選項。
General Configuration應(yī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)
這個選項是一定要選擇的,這樣才能把busybox編譯成靜態(tài)鏈接的可執(zhí)行文件,運(yùn)行時才獨(dú)立于其他函數(shù)庫.否則必需要其他庫文件才能運(yùn)行,在單一個linux內(nèi)核不能使它正常工作.
Installation Options
Don't use /usr
這個選項也一定要選,否則make install 后busybox將安裝在原系統(tǒng)的/usr下,這將覆蓋掉系統(tǒng)原有的命令.選擇這個選項后,make install后會在busybox目錄下生成一個叫_install的目錄,里面有busybox和指向它的鏈接.
其它選項都是一些linux基本命令選項,自己需要哪些命令就編譯進(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目錄下,其他的都是指向他的符號鏈接.
Android系統(tǒng)在超級終端下必會的命令大全(二)
一、安裝和登錄命令
reboot
1.作用
reboot命令的作用是重新啟動計算機(jī),它的使用權(quán)限是系統(tǒng)管理者。
2.格式
reboot [-n] [-w] [-d] [-f] [-i]
3.主要參數(shù)
-n: 在重開機(jī)前不做將記憶體資料寫回硬盤的動作。
-w: 并不會真的重開機(jī),只是把記錄寫到/var/log/wtmp文件里。
-d: 不把記錄寫到/var/log/wtmp文件里(-n這個參數(shù)包含了-d)。
-i: 在重開機(jī)之前先把所有與網(wǎng)絡(luò)相關(guān)的裝置停止。
mount
1.作用
mount命令的作用是加載文件系統(tǒng),它的用權(quán)限是超級用戶或/etc/fstab中允許的使用者。
2.格式
mount -a [-fv] [-t vfstype] [-n] [-rw] [-F] device dir
3.主要參數(shù)
-h:顯示輔助信息。
-v:顯示信息,通常和-f用來除錯。
-a:將/etc/fstab中定義的所有文件系統(tǒng)掛上。
-F:這個命令通常和-a一起使用,它會為每一個mount的動作產(chǎn)生一個行程負(fù)責(zé)執(zhí)行。在系統(tǒng)需要掛上大量NFS文件系統(tǒng)時可以加快加載的速度。
-f:通常用于除錯。它會使mount不執(zhí)行實際掛上的動作,而是模擬整個掛上的過程,通常會和-v一起使用。
-t vfstype:顯示被加載文件系統(tǒng)的類型。
-n:一般而言,mount掛上后會在/etc/mtab中寫入一筆資料,在系統(tǒng)中沒有可寫入文件系統(tǒng)的情況下,可以用這個選項取消這個動作。
4.應(yīng)用技巧
在 Linux和Unix系統(tǒng)上,所有文件都是作為一個大型樹(以/為根)的一部分訪問的。要訪問CD-ROM上的文件,需要將CD-ROM設(shè)備掛裝在文件樹中的某個掛裝點。如果發(fā)行版安裝了自動掛裝包,那么這個步驟可自動進(jìn)行。在Linux中,如果要使用硬盤、光驅(qū)等儲存設(shè)備,就得先將它加載,當(dāng)儲存設(shè)備掛上了之后,就可以把它當(dāng)成一個目錄來訪問。掛上一個設(shè)備使用mount命令。在使用mount這個指令時,至少要先知道下列三種信息:要加載對象的文件系統(tǒng)類型、要加載對象的設(shè)備名稱及要將設(shè)備加載到哪個目錄下。
(1)Linux可以識別的文件系統(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光盤用的文件系統(tǒng):iso9660。
雖然vfat是指FAT 32系統(tǒng),但事實上它也兼容FAT 16的文件系統(tǒng)類型。
(2)確定設(shè)備的名稱
在Linux中,設(shè)備名稱通常都存在/dev里。這些設(shè)備名稱的命名都是有規(guī)則的,可以用“推理”的方式把設(shè)備名稱找出來。例如,/dev/hda1這個
IDE設(shè)備,hd是Hard Disk(硬盤)的,sd是SCSI Device,fd是Floppy Device(或是Floppy
Disk?)。a代表第一個設(shè)備,通常IDE接口可以接上4個IDE設(shè)備(比如4塊硬盤)。所以要識別IDE硬盤的方法分別就是hda、hdb、hdc、
hdd。hda1中的“1”代表hda的第一個硬盤分區(qū)
(partition),hda2代表hda的第二主分區(qū),第一個邏輯分區(qū)從hda5開始,依此類推。此外,可以直接檢查/var/log/messages文件,在該文件中可以找到計算機(jī)開機(jī)后系統(tǒng)已辨認(rèn)出來的設(shè)備代號。
(3)查找掛接點
在決定將設(shè)備掛接之前,先要查看一下計算機(jī)是不是有個/mnt的空目錄,該目錄就是專門用來當(dāng)作掛載點(MountPoint)的目錄。建議在/mnt里建幾個/mnt/cdrom、/mnt/floppy、/mnt/mo等目錄,當(dāng)作目錄的專用掛載點。舉例而言,如要掛載下列5個設(shè)備,其執(zhí)行指令可能如下 (假設(shè)都是Linux的ext2系統(tǒng),如果是Windows XX請將ext2改成vfat):
軟盤 ===>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
不過目前大多數(shù)較新的Linux發(fā)行版本(包括紅旗 Linux、中軟Linux、Mandrake Linux等)都可以自動掛裝文件系統(tǒng),但Red Hat Linux除外。
umount
1.作用
umount命令的作用是卸載一個文件系統(tǒng),它的使用權(quán)限是超級用戶或/etc/fstab中允許的使用者。
2.格式
unmount -a [-fFnrsvw] [-t vfstype] [-n] [-rw] [-F] device dir
3.使用說明
umount
命令是mount命令的逆操作,它的參數(shù)和使用方法和mount命令是一樣的。Linux掛裝CD-ROM后,會鎖定CD—ROM,這樣就不能用CD-
ROM面板上的Eject按鈕彈出它。但是,當(dāng)不再需要光盤時,如果已將/cdrom作為符號鏈接,請使用umount/cdrom來卸裝它。僅當(dāng)無用戶
正在使用光盤時,該命令才會成功。該命令包括了將帶有當(dāng)前工作目錄當(dāng)作該光盤中的目錄的終端窗口。
exit
1.作用
exit命令的作用是退出系統(tǒng),它的使用權(quán)限是所有用戶。
2.格式
exit
3.參數(shù)
exit命令沒有參數(shù),運(yùn)行后退出系統(tǒng)進(jìn)入登錄界面。
--------------------------------------------------------------------------------
作者: ☆-☆ 時間: 2010-6-8 11:52
Android系統(tǒng)在超級終端下必會的命令大全(三)
二、文件處理命令
mkdir
1.作用
mkdir命令的作用是建立名稱為dirname的子目錄,與MS DOS下的md命令類似,它的使用權(quán)限是所有用戶。
2.格式
mkdir [options] 目錄名
3.[options]主要參數(shù)
-m, --mode=模式:設(shè)定權(quán)限,與chmod類似。
-p, --parents:需要時創(chuàng)建上層目錄;如果目錄早已存在,則不當(dāng)作錯誤。
-v, --verbose:每次創(chuàng)建新目錄都顯示信息。
--version:顯示版本信息后離開。
4.應(yīng)用實例
在進(jìn)行目錄創(chuàng)建時可以設(shè)置目錄的權(quán)限,此時使用的參數(shù)是“-m”。假設(shè)要創(chuàng)建的目錄名是“tsk”,讓所有用戶都有rwx(即讀、寫、執(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:只輸出匹配行的計數(shù)。
-I:不區(qū)分大小寫(只適用于單字符)。
-h:查詢多文件時不顯示文件名。
-l:查詢多文件時只輸出包含匹配字符的文件名。
-n:顯示匹配行及行號。
-s:不顯示不存在或無匹配文本的錯誤信息。
-v:顯示不包含匹配文本的所有行。
pattern正則表達(dá)式主要參數(shù):
\:忽略正則表達(dá)式中特殊字符的原有含義。
^:匹配正則表達(dá)式的開始行。
$: 匹配正則表達(dá)式的結(jié)束行。
\:到匹配正則表達(dá)式的行結(jié)束。
[ ]:單個字符,如[A]即A符合要求 。
[ - ]:范圍,如[A-Z],即A、B、C一直到Z都符合要求 。
。:所有的單個字符。
* :有字符,長度可以為0。
正則表達(dá)式是Linux/Unix系統(tǒng)中非常重要的概念。正則表達(dá)式(也稱為“regex”或“regexp”)是一個可以描述一類字符串的模式(Pattern)。如果一個字符串可以用某個正則表達(dá)式來描述,我們就說這個字符和該正則表達(dá)式匹配(Match)。這和DOS中用戶可以使用通配符
“*”代表任意字符類似。在Linux系統(tǒng)上,正則表達(dá)式通常被用來查找文本的模式,以及對文本執(zhí)行“搜索-替換”操作和其它功能。
4.應(yīng)用實例
查詢DNS服務(wù)是日常工作之一,這意味著要維護(hù)覆蓋不同網(wǎng)絡(luò)的大量IP地址。有時IP地址會超過2000個。如果要查看nnn.nnn網(wǎng)絡(luò)地址,但是卻忘了第二部分中的其余部分,只知到有兩個句點,例如nnn nn..。要抽取其中所有nnn.nnn IP地址,使用[0-9 ]\{3
\}\.[0-0\{3\}\。含義是任意數(shù)字出現(xiàn)3次,后跟句點,接著是任意數(shù)字出現(xiàn)3次,后跟句點。
$grep ’[0-9 ]\{3 \}\.[0-0\{3\}\’ ipfile
補(bǔ)充說明,grep家族還包括fgrep和egrep。fgrep是fix grep,允許查找字符串而不是一個模式;egrep是擴(kuò)展grep,支持基本及擴(kuò)展的正則表達(dá)式,但不支持\q模式范圍的應(yīng)用及與之相對應(yīng)的一些更加規(guī)范的模式。
dd
1.作用
dd命令用來復(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ù)以逗號分隔的關(guān)鍵字表示的方式來轉(zhuǎn)換文件。
count=塊數(shù)目:只復(fù)制指定的輸入數(shù)據(jù)。
ibs=字節(jié):每次讀取指定的。
if=文件:讀取內(nèi)容,而非標(biāo)準(zhǔn)輸入的數(shù)據(jù)。
obs=字節(jié):每次寫入指定的。
of=文件:將數(shù)據(jù)寫入,而不在標(biāo)準(zhǔn)輸出顯示。
seek=塊數(shù)目:先略過以obs為單位的指定的輸出數(shù)據(jù)。
skip=塊數(shù)目:先略過以ibs為單位的指定的輸入數(shù)據(jù)。
4.應(yīng)用實例
dd命令常常用來制作Linux啟動盤。先找一個可引導(dǎo)內(nèi)核,令它的根設(shè)備指向正確的根分區(qū),然后使用dd命令將其寫入軟盤:
$ rdev vmlinuz /dev/hda
$dd if=vmlinuz of=/dev/fd0
上面代碼說明,使用rdev命令將可引導(dǎo)內(nèi)核vmlinuz中的根設(shè)備指向/dev/hda,請把“hda”換成自己的根分區(qū),接下來用dd命令將該內(nèi)核寫入軟盤。
find
1.作用
find命令的作用是在目錄中搜索文件,它的使用權(quán)限是所有用戶。
2.格式
find [path][options][expression]
path指定目錄路徑,系統(tǒng)從這里開始沿著目錄樹向下查找文件。它是一個路徑列表,相互用空格分離,如果不寫path,那么默認(rèn)為當(dāng)前目錄。
3.主要參數(shù)
[options]參數(shù):
-depth:使用深度級別的查找過程方式,在某層指定目錄中優(yōu)先查找文件內(nèi)容。
-maxdepth levels:表示至多查找到開始目錄的第level層子目錄。level是一個非負(fù)數(shù),如果level是0的話表示僅在當(dāng)前目錄中查找。
-mindepth levels:表示至少查找到開始目錄的第level層子目錄。
-mount:不在其它文件系統(tǒng)(如Msdos、Vfat等)的目錄和文件中查找。
-version:打印版本。
[expression]是匹配表達(dá)式,是find命令接受的表達(dá)式,find命令的所有操作都是針對表達(dá)式的。它的參數(shù)非常多,這里只介紹一些常用的參數(shù)。
—name:支持統(tǒng)配符*和?。
-atime n:搜索在過去n天讀取過的文件。
-ctime n:搜索在過去n天修改過的文件。
-group grpoupname:搜索所有組為grpoupname的文件。
-user 用戶名:搜索所有文件屬主為用戶名(ID或名稱)的文件。
-size n:搜索文件大小是n個block的文件。
-print:輸出搜索結(jié)果,并且打印。
4.應(yīng)用技巧
find命令查找文件的幾種方法:
(1)根據(jù)文件名查找
例如,我們想要查找一個文件名是lilo.conf的文件,可以使用如下命令:
find / -name lilo.conf
find命令后的“/”表示搜索整個硬盤。
(2)快速查找文件
根據(jù)文件名查找文件會遇到一個實際問題,就是要花費(fèi)相當(dāng)長的一段時間,特別是大型Linux文件系統(tǒng)和大容量硬盤文件放在很深的子目錄中時。如果我們知道了這個文件存放在某個目錄中,那么只要在這個目錄中往下尋找就能節(jié)省很多時間。比如smb.conf文件,從它的文件后綴“.conf”可以判斷這是一個配置文件,那么它應(yīng)該在/etc目錄內(nèi),此時可以使用下面命令:
find /etc -name smb.conf
這樣,使用“快速查找文件”方式可以縮短時間。
(3)根據(jù)部分文件名查找方法
有時我們知道只某個文件包含有abvd這4個字,那么要查找系統(tǒng)中所有包含有這4個字符的文件可以輸入下面命令:
find / -name ’*abvd*’
輸入這個命令以后,Linux系統(tǒng)會將在/目錄中查找所有的包含有abvd這4個字符的文件(其中*是通配符),比如abvdrmyz等符合條件的文件都能顯示出來。
(4) 使用混合查找方式查找文件
find命令可以使用混合查找的方法,例如,我們想在/etc目錄中查找大于500000字節(jié),并且在24小時內(nèi)修改的某個文件,則可以使用-and (與)把兩個查找參數(shù)鏈接起來組合成一個混合的查找方式。
find /etc -size +500000c -and -mtime +1
mv
1.作用
mv命令用來為文件或目錄改名,或者將文件由一個目錄移入另一個目錄中,它的使用權(quán)限是所有用戶。該命令如同DOS命令中的ren和move的組合。
2.格式
mv[options] 源文件或目錄 目標(biāo)文件或目錄
3.[options]主要參數(shù)
-i:交互方式操作。如果mv操作將導(dǎo)致對已存在的目標(biāo)文件的覆蓋,此時系統(tǒng)詢問是否重寫,要求用戶回答“y”或“n”,這樣可以避免誤覆蓋文件。
-f:禁止交互操作。mv操作要覆蓋某個已有的目標(biāo)文件時不給任何指示,指定此參數(shù)后i參數(shù)將不再起作用。
4.應(yīng)用實例
(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:不隱藏任何以“.” 字符開始的項目。
-A, --almost-all:列出除了“ . ”及 “.. ”以外的任何項目。
--author:印出每個文件著作者。
-b, --escape:以八進(jìn)制溢出序列表示不可打印的字符。
--block-size=大小:塊以指定的字節(jié)為單位。
-B, --ignore-backups:不列出任何以 ~ 字符結(jié)束的項目。
-f:不進(jìn)行排序,-aU參數(shù)生效,-lst參數(shù)失效。
-F, --classify:加上文件類型的指示符號 (*/=@| 其中一個)。
-g:like -l, but do not list owner。
-G, --no-group:inhibit display of group information。
-i, --inode:列出每個文件的inode號。
-I, --ignore=樣式:不印出任何符合Shell萬用字符的項目。
-k:即--block-size=1K。
-l:使用較長格式列出信息。
-L, --dereference:當(dāng)顯示符號鏈接的文件信息時,顯示符號鏈接所指示的對象,而并非符號鏈接本身的信息。
-m:所有項目以逗號分隔,并填滿整行行寬。
-n, --numeric-uid-gid:類似-l,但列出UID及GID號。
-N, --literal:列出未經(jīng)處理的項目名稱,例如不特別處理控制字符。
-p, --file-type:加上文件類型的指示符號 (/=@| 其中一個)。
-Q, --quote-name:將項目名稱括上雙引號。
-r, --reverse:依相反次序排列。
-R, --recursive:同時列出所有子目錄層。
-s, --size:以塊大小為序。
4.應(yīng)用舉例
ls
命令是Linux系統(tǒng)使用頻率最多的命令,它的參數(shù)也是Linux命令中最多的。使用ls命令時會有幾種不同的顏色,其中藍(lán)色表示是目錄,綠色表示是可執(zhí)
行文件,紅色表示是壓縮文件,淺藍(lán)色表示是鏈接文件,加粗的黑色表示符號鏈接,灰色表示是其它格式文件。ls最常使用的是ls- l。
文
件類型開頭是由10個字符構(gòu)成的字符串。其中第一個字符表示文件類型,它可以是下述類型之一:-(普通文件)、d(目錄)、l(符號鏈接)、b(塊設(shè)備文件)、c(字符設(shè)備文件)。后面的9個字符表示文件的訪問權(quán)限,分為3組,每組3位。第一組表示文件屬主的權(quán)限,第二組表示同組用戶的權(quán)限,第三組表示其他用戶的權(quán)限。每一組的三個字符分別表示對文件的讀(r)、寫(w)和執(zhí)行權(quán)限(x)。對于目錄,表示進(jìn)入權(quán)限。s表示當(dāng)文件被執(zhí)行時,把該文件的UID 或GID賦予執(zhí)行進(jìn)程的UID(用戶ID)或GID(組ID)。t表示設(shè)置標(biāo)志位(留在內(nèi)存,不被換出)。如果該文件是目錄,那么在該目錄中的文件只能被超級用戶、目錄擁有者或文件屬主刪除。如果它是可執(zhí)行文件,那么在該文件執(zhí)行后,指向其正文段的指針仍留在內(nèi)存。這樣再次執(zhí)行它時,系統(tǒng)就能更快地裝入該文件。接著顯示的是文件大小、生成時間、文件或命令名稱。
Android系統(tǒng)在超級終端下必會的命令大全(四)
diff
1.作用
diff命令用于兩個文件之間的比較,并指出兩者的不同,它的使用權(quán)限是所有用戶。
2.格式
diff [options] 源文件 目標(biāo)文件
3.[options]主要參數(shù)
-a:將所有文件當(dāng)作文本文件來處理。
-b:忽略空格造成的不同。
-B:忽略空行造成的不同。
-c:使用綱要輸出格式。
-H:利用試探法加速對大文件的搜索。
-I:忽略大小寫的變化。
-n --rcs:輸出RCS格式。
cmp
1.作用
cmp(“compare”的縮寫)命令用來簡要指出兩個文件是否存在差異,它的使用權(quán)限是所有用戶。
2.格式
cmp[options] 文件名
3.[options]主要參數(shù)
-l: 將字節(jié)以十進(jìn)制的方式輸出,并方便將兩個文件中不同的以八進(jìn)制的方式輸出。
cat
1.作用
cat(“concatenate”的縮寫)命令用于連接并顯示指定的一個和多個文件的有關(guān)信息,它的使用權(quán)限是所有用戶。
2.格式
cat [options] 文件1 文件2……
3.[options]主要參數(shù)
-n:由第一行開始對所有輸出的行數(shù)編號。
-b:和-n相似,只不過對于空白行不編號。
-s:當(dāng)遇到有連續(xù)兩行以上的空白行時,就代換為一行的空白行。
4.應(yīng)用舉例
(1)cat命令一個最簡單的用處是顯示文本文件的內(nèi)容。例如,我們想在命令行看一下README文件的內(nèi)容,可以使用命令:
$ cat README
(2)有時需要將幾個文件處理成一個文件,并將這種處理的結(jié)果保存到一個單獨(dú)的輸出文件。cat命令在其輸入上接受一個或多個文件,并將它們作為一個單獨(dú)的文件打印到它的輸出。例如,把README和INSTALL的文件內(nèi)容加上行號(空白行不加)之后,將內(nèi)容附加到一個新文本文件File1 中:
$ cat README INSTALL File1
(3)cat 還有一個重要的功能就是可以對行進(jìn)行編號。這種功能對于程序文檔的編制,以及法律和科學(xué)文檔的編制很方便,打印在左邊的行號使得參考文檔的某一部分變得容易,這些在編程、科學(xué)研究、業(yè)務(wù)報告甚至是立法工作中都是非常重要的。對行進(jìn)行編號功能有-b(只能對非空白行進(jìn)行編號)和-n(可以對所有行進(jìn)行編號)兩個參數(shù):
$ cat -b /etc/named.conf
ln
1.作用
ln命令用來在文件之間創(chuàng)建鏈接,它的使用權(quán)限是所有用戶。
2.格式
ln [options] 源文件 [鏈接名]
3.參數(shù)
-f:鏈結(jié)時先將源文件刪除。
-d:允許系統(tǒng)管理者硬鏈結(jié)自己的目錄。
-s:進(jìn)行軟鏈結(jié)(Symbolic Link)。
-b:將在鏈結(jié)時會被覆蓋或刪除的文件進(jìn)行備份。
鏈接有兩種,一種被稱為硬鏈接(Hard Link),另一種被稱為符號鏈接(Symbolic Link)。默認(rèn)情況下,ln命令產(chǎn)生硬鏈接。硬連接指通過索引節(jié)點來進(jìn)行的連接。在Linux的文件系統(tǒng)中,保存在磁盤分區(qū)中的文件不管是什么類型都給它分配一個編號,稱為索引節(jié)點號(InodeIndex)。在Linux中,多個文件名指向同一索引節(jié)點是存在的。一般這種連接就是硬連接。硬連接的作用是允許一個文件擁有多個有效路徑名,這樣用戶就可以建立硬連接到重要文件,以防止“誤刪”的功能。其原因如上所述,因為對應(yīng)該目錄的索引節(jié)點有一個以上的連接。只刪除一個連接并不影響索引節(jié)點本身和其它的連接,只有當(dāng)最后一個連接被刪除后,文件的數(shù)據(jù)塊及目錄的連接才會被釋放。也就是說,文件才會被真正刪除。與硬連接相對應(yīng),Lnux系統(tǒng)中還存在另一種連接,稱為符號連接(Symbilc Link),也叫軟連接。軟鏈接文件有點類似于Windows的快捷方式。它實際上是特殊文件的一種。在符號連接中,文件實際上是一個文本文件,其中包含的有另一文件的位置信息。
--------------------------------------------------------------------------------
作者: ☆-☆ 時間: 2010-6-8 11:55
本帖最后由 ☆-☆ 于 2010-6-8 11:59 編輯
Android系統(tǒng)在超級終端下必會的命令大全(五)
系統(tǒng)管理命令
df
1.作用
df命令用來檢查文件系統(tǒng)的磁盤空間占用情況,使用權(quán)限是所有用戶。
2.格式
df [options]
3.主要參數(shù)
-s:對每個Names參數(shù)只給出占用的數(shù)據(jù)塊總數(shù)。
-a:遞歸地顯示指定目錄中各文件及子目錄中各文件占用的數(shù)據(jù)塊數(shù)。若既不指定-s,也不指定-a,則只顯示Names中的每一個目錄及其中的各子目錄所占的磁盤塊數(shù)。
-k:以1024字節(jié)為單位列出磁盤空間使用情況。
-x:跳過在不同文件系統(tǒng)上的目錄不予統(tǒng)計。
-l:計算所有的文件大小,對硬鏈接文件則計算多次。
-i:顯示inode信息而非塊使用量。
-h:以容易理解的格式印出文件系統(tǒng)大小,例如136KB、254MB、21GB。
-P:使用POSIX輸出格式。
-T:顯示文件系統(tǒng)類型。
4.說明
df 命令被廣泛地用來生成文件系統(tǒng)的使用統(tǒng)計數(shù)據(jù),它能顯示系統(tǒng)中所有的文件系統(tǒng)的信息,包括總?cè)萘俊⒖捎玫目臻e空間、目前的安裝點等。超級權(quán)限用戶使用df 命令時會發(fā)現(xiàn)這樣的情況:某個分區(qū)的容量超過了100%。這是因為Linux系統(tǒng)為超級用戶保留了10%的空間,由其單獨(dú)支配。也就是說,對于超級用戶而言,他所見到的硬盤容量將是110%。這樣的安排對于系統(tǒng)管理而言是有好處的,當(dāng)硬盤被使用的容量接近100%時系統(tǒng)管理員還可以正常工作。
5.應(yīng)用實例
Linux支持的文件系統(tǒng)非常多,包括JFS、ReiserFS、ext、ext2、ext3、ISO9660、XFS、Minx、vfat、MSDOS等。使用df -T命令查看磁盤空間時還可以得到文件系統(tǒng)的信息:
#df -T
文件系統(tǒng) 類型 容量 已用 可用 已用% 掛載點
/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
從上面除了可以看到磁盤空間的容量、使用情況外,分區(qū)的文件系統(tǒng)類型、掛載點等信息也一覽無遺。
top
1.作用
top命令用來顯示執(zhí)行中的程序進(jìn)程,使用權(quán)限是所有用戶。
2.格式
top [-] [d delay] [q] [c] [S] [n]
3.主要參數(shù)
d:指定更新的間隔,以秒計算。
q:沒有任何延遲的更新。如果使用者有超級用戶,則top命令將會以最高的優(yōu)先序執(zhí)行。
c:顯示進(jìn)程完整的路徑與名稱。
S:累積模式,會將己完成或消失的子行程的CPU時間累積起來。
s:安全模式。
i:不顯示任何閑置(Idle)或無用(Zombie)的行程。
n:顯示更新的次數(shù),完成后將會退出top。
4.說明
top命令是Linux系統(tǒng)管理的一個主要命令,通過它可以獲得許多信息。
下面列出了詳細(xì)解釋。
PID(Process ID):進(jìn)程標(biāo)示號。
USER:進(jìn)程所有者的用戶名。
PR:進(jìn)程的優(yōu)先級別。
NI:進(jìn)程的優(yōu)先級別數(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)程啟動后占用的總的CPU時間。
Command:進(jìn)程啟動的啟動命令名稱,如果這一行顯示不下,進(jìn)程會有一個完整的命令行。
top命令使用過程中,還可以使用一些交互的命令來完成其它參數(shù)的功能。這些命令是通過快捷鍵啟動的。
:立刻刷新。
P:根據(jù)CPU使用大小進(jìn)行排序。
T:根據(jù)時間、累計時間排序。
q:退出top命令。
m:切換顯示內(nèi)存信息。
t:切換顯示進(jìn)程和CPU狀態(tài)信息。
c:切換顯示命令名稱和完整命令行。
M:根據(jù)使用內(nèi)存大小進(jìn)行排序。
W:將當(dāng)前設(shè)置寫入~/.toprc文件中。這是寫top配置文件的推薦方法。
可以看到,top命令是一個功能十分強(qiáng)大的監(jiān)控系統(tǒng)的工具,對于系統(tǒng)管理員而言尤其重要。但是,它的缺點是會消耗很多系統(tǒng)資源。
free
1.作用
free命令用來顯示內(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ù)來顯示一次內(nèi)存使用情況。
-t:顯示內(nèi)存總和列。
-o:不顯示緩沖區(qū)調(diào)節(jié)列。
4.應(yīng)用實例
free命令是用來查看內(nèi)存使用情況的主要命令。和top命令相比,它的優(yōu)點是使用簡單,并且只占用很少的系統(tǒng)資源。通過-S參數(shù)可以使用free命令不間斷地監(jiān)視有多少內(nèi)存在使用,這樣可以把它當(dāng)作一個方便實時監(jiān)控器。
#free -b -s5
使用這個命令后終端會連續(xù)不斷地報告內(nèi)存使用情況(以字節(jié)為單位),每5秒更新一次。
chown
1.作用
更改一個或多個文件或目錄的屬主和屬組。使用權(quán)限是超級用戶。
2.格式
chown [選項] 用戶或組 文件
3.主要參數(shù)
--dereference:受影響的是符號鏈接所指示的對象,而非符號鏈接本身。
-h, --no-dereference:會影響符號鏈接本身,而非符號鏈接所指示的目的地(當(dāng)系統(tǒng)支持更改符號鏈接的所有者,此選項才有效)。
--from=目前所有者:目前組只當(dāng)每個文件的所有者和組符合選項所指定的,才會更改所有者和組。其中一個可以省略,這已省略的屬性就不需要符合原有的屬性。
-f, --silent, --quiet:去除大部分的錯誤信息。
-R, --recursive:遞歸處理所有的文件及子目錄。
-v, --verbose:處理任何文件都會顯示信息。
4.說明
chown 將指定文件的擁有者改為指定的用戶或組,用戶可以是用戶名或用戶ID;組可以是組名或組ID;文件是以空格分開的要改變權(quán)限的文件列表,支持通配符。系統(tǒng)管理員經(jīng)常使用chown命令,在將文件拷貝到另一個用戶的目錄下以后,讓用戶擁有使用該文件的權(quán)限。
5.應(yīng)用實例
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)限超級用戶。
2.格式
chattr [-RV] [-+=AacDdijsSu] [-v version] 文件或目錄
3.主要參數(shù)
-R:遞歸處理所有的文件及子目錄。
-V:詳細(xì)顯示修改內(nèi)容,并打印輸出。
-:失效屬性。
+:激活屬性。
= :指定屬性。
A:Atime,告訴系統(tǒng)不要修改對這個文件的最后訪問時間。
S:Sync,一旦應(yīng)用程序?qū)@個文件執(zhí)行了寫操作,使系統(tǒng)立刻把修改的結(jié)果寫到磁盤。
a:Append Only,系統(tǒng)只允許在這個文件之后追加數(shù)據(jù),不允許任何進(jìn)程覆蓋或截斷這個文件。如果目錄具有這個屬性,系統(tǒng)將只允許在這個目錄下建立和修改文件,而不允許刪除任何文件。
i:Immutable,系統(tǒng)不允許對這個文件進(jìn)行任何的修改。如果目錄具有這個屬性,那么任何的進(jìn)程只能修改目錄之下的文件,不允許建立和刪除文件。
D:檢查壓縮文件中的錯誤。
d:No dump,在進(jìn)行文件系統(tǒng)備份時,dump程序?qū)⒑雎赃@個文件。
C:Compress,系統(tǒng)以透明的方式壓縮這個文件。從這個文件讀取時,返回的是解壓之后的數(shù)據(jù);而向這個文件中寫入數(shù)據(jù)時,數(shù)據(jù)首先被壓縮之后才寫入磁盤。
s:Secure Delete,讓系統(tǒng)在刪除這個文件時,使用0填充文件所在的區(qū)域。
u:Undelete,當(dāng)一個應(yīng)用程序請求刪除這個文件,系統(tǒng)會保留其數(shù)據(jù)塊以便以后能夠恢復(fù)刪除這個文件。
4.說明
chattr
命令的作用很大,其中一些功能是由Linux內(nèi)核版本來支持的,如果Linux內(nèi)核版本低于2.2,那么許多功能不能實現(xiàn)。同樣-D檢查壓縮文件中的錯誤
的功能,需要2.5.19以上內(nèi)核才能支持。另外,通過chattr命令修改屬性能夠提高系統(tǒng)的安全性,但是它并不適合所有的目錄。chattr命令不能
保護(hù)/、/dev、/tmp、/var目錄。
5.應(yīng)用實例
1.恢復(fù)/root目錄,即子目錄的所有文件
# chattr -R +u/root
2.用chattr命令防止系統(tǒng)中某個關(guān)鍵文件被修改
在Linux下,有些配置文件(passwd ,fatab)是不允許任何人修改的,為了防止被誤刪除或修改,可以設(shè)定該文件的“不可修改位(immutable)”,命令如下:
# chattr +i /etc/fstab
ps
1.作用
ps顯示瞬間進(jìn)程 (process) 的動態(tài),使用權(quán)限是所有使用者。
2.格式
ps [options] [--help]
3.主要參數(shù)
ps的參數(shù)非常多, 此出僅列出幾個常用的參數(shù)。
-A:列出所有的進(jìn)程。
-l:顯示長列表。
-m:顯示內(nèi)存信息。
-w:顯示加寬可以顯示較多的信息。
-e:顯示所有進(jìn)程。
a:顯示終端上的所有進(jìn)程,包括其它用戶的進(jìn)程。
-au:顯示較詳細(xì)的信息。
-aux:顯示所有包含其它使用者的進(jìn)程。
4.說明
要
對進(jìn)程進(jìn)行監(jiān)測和控制,首先要了解當(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)程有沒有僵尸、哪些進(jìn)程占用了過多的資源等。圖2給出了ps-aux命令詳解。大部分信息都可以通過執(zhí)行該命
令得到。最常用的三個參數(shù)是u、a、x。下面就結(jié)合這三個參數(shù)詳細(xì)說明ps命令的作用:ps aux
圖2 ps-aux命令詳解
圖2第2行代碼中,USER表示進(jìn)程擁有者;PID表示進(jìn)程標(biāo)示符;%CPU表示占用的CPU使用率;%MEM占用的物理內(nèi)存使用率;VSZ表示占用的虛擬內(nèi)存大小;RSS為進(jìn)程占用的物理內(nèi)存值;TTY為終端的次要裝置號碼。
STAT
表示進(jìn)程的狀態(tài),其中D為不可中斷的靜止(I/O動作);R正在執(zhí)行中;S靜止?fàn)顟B(tài);T暫停執(zhí)行;Z不存在,但暫時無法消除;W沒有足夠的內(nèi)存分頁可分
配;高優(yōu)先序的進(jìn)程;N低優(yōu)先序的進(jìn)程;L有內(nèi)存分頁分配并鎖在內(nèi)存體內(nèi) (實時系統(tǒng)或
I/O)。START為進(jìn)程開始時間。TIME為執(zhí)行的時間。COMMAND是所執(zhí)行的指令。
4.應(yīng)用實例
在進(jìn)行系統(tǒng)維護(hù)時,經(jīng)常會出現(xiàn)內(nèi)存使用量驚人,而又不知道是哪一個進(jìn)程占用了大量進(jìn)程的情況。除了可以使用top命令查看內(nèi)存使用情況之外,還可以使用下面的命令:
ps aux | sort +5n
--------------------------------------------------------------------------------
作者: ☆-☆ 時間: 2010-6-8 11:58
Android系統(tǒng)在超級終端下必會的命令大全(十)
六、其他命令
tar
1.作用
tar命令是Unix/Linux系統(tǒng)中備份文件的可靠方法,幾乎可以工作于任何環(huán)境中,它的使用權(quán)限是所有用戶。
2.格式
tar [主選項+輔選項] 文件或目錄
3.主要參數(shù)
使用該命令時,主選項是必須要有的,它告訴tar要做什么事情,輔選項是輔助使用的,可以選用。
主選項:
-c 創(chuàng)建新的檔案文件。如果用戶想備份一個目錄或是一些文件,就要選擇這個選項。
-r 把要存檔的文件追加到檔案文件的未尾。例如用戶已經(jīng)做好備份文件,又發(fā)現(xiàn)還有一個目錄或是一些文件忘記備份了,這時可以使用該選項,將忘記的目錄或文件追加到備份文件中。
-t 列出檔案文件的內(nèi)容,查看已經(jīng)備份了哪些文件。
-u 更新文件。就是說,用新增的文件取代原備份文件,如果在備份文件中找不到要更新的文件,則把它追加到備份文件的最后。
-x 從檔案文件中釋放文件。
輔助選項:
-b 該選項是為磁帶機(jī)設(shè)定的,其后跟一數(shù)字,用來說明區(qū)塊的大小,系統(tǒng)預(yù)設(shè)值為20(20×512 bytes)。
-f 使用檔案文件或設(shè)備,這個選項通常是必選的。
-k 保存已經(jīng)存在的文件。例如把某個文件還原,在還原的過程中遇到相同的文件,不會進(jìn)行覆蓋。
-m 在還原文件時,把所有文件的修改時間設(shè)定為現(xiàn)在。
-M 創(chuàng)建多卷的檔案文件,以便在幾個磁盤中存放。
-v 詳細(xì)報告tar處理的文件信息。如無此選項,tar不報告文件信息。
-w 每一步都要求確認(rèn)。
-z 用gzip來壓縮/解壓縮文件,加上該選項后可以將檔案文件進(jìn)行壓縮,但還原時也一定要使用該選項進(jìn)行解壓縮。
4.應(yīng)用說明
tar 是Tape Archive(磁帶歸檔)的縮寫,最初設(shè)計用于將文件打包到磁帶上。如果下載過Linux的源代碼,或許已經(jīng)碰到過tar文件
請注意,不要忘了Linux是區(qū)分大小寫的。例如,tar命令應(yīng)該總是以小寫的形式執(zhí)行。命令行開關(guān)可以是大寫、小寫或大小寫的混合。例如,-t和-T執(zhí)行不同的功能。文件或目錄名稱可以混合使用大小寫,而且就像命令和命令行開關(guān)一樣是區(qū)分大小寫的。
5.應(yīng)用實例
tar是一個命令行的工具,沒有圖形界面。使用Konsole打開一個終端窗口,接下來是一個簡單的備份命令(在/temp目錄中創(chuàng)建一個back.tar的文件,/usr目錄中所有內(nèi)容都包含在其中。):
$tar cvf - /usr > /temp/back.tar
另
外,tar命令支持前面第三講中講過的crontab命令,可以用crontab工具設(shè)置成基于時間的有規(guī)律地運(yùn)行。例如,每晚6點把/usr目錄備份到
hda—第一個IDE接口的主驅(qū)動器 (總是位于第一個硬盤)中,只要將下面語句添加到root的crontab中即可:
$00 06 * * * tar cvf /dev/hda1/usrfiles.tar - /usr
一般情況下,以下這些目錄是需要備份的:
◆/etc 包含所有核心配置文件,其中包括網(wǎng)絡(luò)配置、系統(tǒng)名稱、防火墻規(guī)則、用戶、組,以及其它全局系統(tǒng)項。
◆ /var 包含系統(tǒng)守護(hù)進(jìn)程(服務(wù))所使用的信息,包括DNS配置、DHCP租期、郵件緩沖文件、HTTP服務(wù)器文件、dB2實例配置等。
◆/home 包含所有默認(rèn)用戶的主目錄,包括個人設(shè)置、已下載的文件和用戶不希望失去的其它信息。
◆/root 根(root)用戶的主目錄。
◆/opt 是安裝許多非系統(tǒng)文件的地方。IBM軟件就安裝在這里。OpenOffice、JDK和其它軟件在默認(rèn)情況下也安裝在這里。
有些目錄是可以不備份的:
◆ /proc 應(yīng)該永遠(yuǎn)不要備份這個目錄。它不是一個真實的文件系統(tǒng),而是運(yùn)行內(nèi)核和環(huán)境的虛擬化視圖,包括諸如/proc/kcore這樣的文件,這個文件是整個運(yùn)行內(nèi)存的虛擬視圖。備份這些文件只是在浪費(fèi)資源。
◆/dev 包含硬件設(shè)備的文件表示。如果計劃還原到一個空白的系統(tǒng),就可以備份/dev。然而,如果計劃還原到一個已安裝的Linux 系統(tǒng),那么備份/dev是沒有必要的。
unzip
1.作用
unzip
命令位于/usr/bin目錄中,它們和MS DOS下的pkzip、pkunzip及MS
Windows中的Winzip軟件功能一樣,將文件壓縮成.zip文件,以節(jié)省硬盤空間,當(dāng)需要的時候再將壓縮文件用unzip命令解開。該命令使用權(quán)
限是所有用戶。
2.格式
unzip [-cflptuvz][-agCjLMnoqsVX][-P ][.zip文件][文件][-d ][-x ]
3.主要參數(shù)
-c:將解壓縮的結(jié)果顯示到屏幕上,并對字符做適當(dāng)?shù)霓D(zhuǎn)換。
-f:更新現(xiàn)有的文件。
-l:顯示壓縮文件內(nèi)所包含的文件。
-p:與-c參數(shù)類似,會將解壓縮的結(jié)果顯示到屏幕上,但不會執(zhí)行任何的轉(zhuǎn)換。
-t:檢查壓縮文件是否正確。
-u:與-f參數(shù)類似,但是除了更新現(xiàn)有的文件外,也會將壓縮文件中的其它文件解壓縮到目錄中。
-v:執(zhí)行是時顯示詳細(xì)的信息。
-z:僅顯示壓縮文件的備注文字。
-a:對文本文件進(jìn)行必要的字符轉(zhuǎn)換。
-b:不要對文本文件進(jìn)行字符轉(zhuǎn)換。
-C:壓縮文件中的文件名稱區(qū)分大小寫。
-j:不處理壓縮文件中原有的目錄路徑。
-L:將壓縮文件中的全部文件名改為小寫。
-M:將輸出結(jié)果送到more程序處理。
-n:解壓縮時不要覆蓋原有的文件。
-o:不必先詢問用戶,unzip執(zhí)行后覆蓋原有文件。
-P:使用zip的密碼選項。
-q:執(zhí)行時不顯示任何信息。
-s:將文件名中的空白字符轉(zhuǎn)換為底線字符。
-V:保留VMS的文件版本信息。
-X:解壓縮時同時回存文件原來的UID/GID。
[.zip文件]:指定.zip壓縮文件。
[文件]:指定要處理.zip壓縮文件中的哪些文件。
-d:指定文件解壓縮后所要存儲的目錄。
-x:指定不要處理.zip壓縮文件中的哪些文件。
-Z unzip:-Z等于執(zhí)行zipinfo指令。在Linux中,還提供了一個叫zipinfo的工具,能夠察看zip壓縮文件的詳細(xì)信息。
gunzip
1.作用
gunzip命令作用是解壓文件,使用權(quán)限是所有用戶。
2.格式
gunzip [-acfhlLnNqrtvV][-s ][文件...]
或者
gunzip [-acfhlLnNqrtvV][-s ][目錄]
3.主要參數(shù)
-a或--ascii:使用ASCII文字模式。
-c或--stdout或--to-stdout:把解壓后的文件輸出到標(biāo)準(zhǔn)輸出設(shè)備。
-f或-force:強(qiáng)行解開壓縮文件,不理會文件名稱或硬連接是否存在,以及該文件是否為符號連接。
-h或--help:在線幫助。
-l或--list:列出壓縮文件的相關(guān)信息。
-L或--license:顯示版本與版權(quán)信息。
-n或--no-name:解壓縮時,若壓縮文件內(nèi)含有原來的文件名稱及時間戳記,則將其忽略不予處理。
-N或--name:解壓縮時,若壓縮文件內(nèi)含有原來的文件名稱及時間戳記,則將其回存到解開的文件上。
-q或--quiet:不顯示警告信息。
-r或--recursive:遞歸處理,將指定目錄下的所有文件及子目錄一并處理。
-S或--suffix:更改壓縮字尾字符串。
-t或--test:測試壓縮文件是否正確無誤。
-v或--verbose:顯示指令執(zhí)行過程。
-V或--version:顯示版本信息。
4.說明
gunzip是個使用廣泛的解壓縮程序,它用于解開被gzip壓縮過的文件,這些壓縮文件預(yù)設(shè)最后的擴(kuò)展名為“.gz”。事實上,gunzip就是gzip的硬連接,因此不論是壓縮或解壓縮,都可通過gzip指令單獨(dú)完成。gunzip最新版本是1.3.3 。
那就首先說點Runtime類吧,他是一個與JVM運(yùn)行時環(huán)境有關(guān)的類,這個類是Singleton的。我說幾個自己覺得重要的地方。
1、Runtime.getRuntime()可以取得當(dāng)前JVM的運(yùn)行時環(huán)境,這也是在Java中唯一一個得到運(yùn)行時環(huán)境的方法。
2、Runtime上其他大部分的方法都是實例方法,也就是說每次進(jìn)行運(yùn)行時調(diào)用時都要用到getRuntime方法。
3、 Runtime中的exit方法是退出當(dāng)前JVM的方法,估計也是唯一的一個吧,因為我看到System類中的exit實際上也是通過調(diào)用 Runtime.exit()來退出JVM的,這里說明一下Java對Runtime返回值的一般規(guī)則(后邊也提到了),0代表正常退出,非0代表異常中止,這只是Java的規(guī)則,在各個操作系統(tǒng)中總會發(fā)生一些小的混淆。
4、Runtime.addShutdownHook()方法可以注冊一個hook在JVM執(zhí)行shutdown的過程中,方法的參數(shù)只要是一個初始化過但是沒有執(zhí)行的Thread實例就可以。(注意,Java中的Thread都是執(zhí)行過了就不值錢的哦)
5、說到addShutdownHook這個方法就要說一下JVM運(yùn)行環(huán)境是在什么情況下shutdown或者abort的。文檔上是這樣寫的,當(dāng)最后一個非精靈進(jìn)程退出或者收到了一個用戶中斷信號、用戶登出、系統(tǒng)shutdown、Runtime的exit方法被調(diào)用時JVM會啟動shutdown的過程,在這個過程開始后,他會并行啟動所有登記的shutdown hook(注意是并行啟動,這就需要線程安全和防止死鎖)。當(dāng)shutdown過程啟動后,只有通過調(diào)用halt方法才能中止shutdown的過程并退出JVM。
那什么時候JVM會abort退出那?首先說明一下,abort退出時JVM就是停止運(yùn)行但并不一定進(jìn)行shutdown。這只有JVM在遇到SIGKILL信號或者windows中止進(jìn)程的信號、本地方法發(fā)生類似于訪問非法地址一類的內(nèi)部錯誤時會出現(xiàn)。這種情況下并不能保證shutdown hook是否被執(zhí)行。
現(xiàn)在開始看這篇文章,呵呵。
首先講的是Runtime.exec()方法的所有重載。這里要注意的有一點,就是public Process exec(String [] cmdArray, String [] envp);這個方法中cmdArray是一個執(zhí)行的命令和參數(shù)的字符串?dāng)?shù)組,數(shù)組的第一個元素是要執(zhí)行的命令往后依次都是命令的參數(shù),envp我個人感覺應(yīng)該和C中的execve中的環(huán)境變量是一樣的,envp中使用的是name=value的方式。
<!--[if !supportLists]-->1、 <!--[endif]-->一個很糟糕的調(diào)用程序,代碼如下,這個程序用exec調(diào)用了一個外部命令之后馬上使用exitValue就對其返回值進(jìn)行檢查,讓我們看看會出現(xià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)
這里看原文就可以了解,這里主要的問題就是錯誤的調(diào)用了exitValue來取得外部命令的返回值(呵呵,這個錯誤我也曾經(jīng)犯過),因為exitValue 這個方法是不阻塞的,程序在調(diào)用這個方法時外部命令并沒有返回所以造成了異常的出現(xiàn),這里是由另外的方法來等待外部命令執(zhí)行完畢的,就是waitFor方法,這個方法會一直阻塞直到外部命令執(zhí)行結(jié)束,然后返回外部命令執(zhí)行的結(jié)果,作者在這里一頓批評設(shè)計者的思路有問題,呵呵,反正我是無所謂阿,能用就可以拉。但是作者在這里有一個說明,就是exitValue也是有好多用途的。因為當(dāng)你在一個Process上調(diào)用waitFor方法時,當(dāng)前線程是阻塞的,如果外部命令無法執(zhí)行結(jié)束,那么你的線程就會一直阻塞下去,這種意外會影響我們程序的執(zhí)行。所以在我們不能判斷外部命令什么時候執(zhí)行完畢而我們的程序還需要繼續(xù)執(zhí)行的情況下,我們就應(yīng)該循環(huán)的使用exitValue來取得外部命令的返回狀態(tài),并在外部命令返回時作出相應(yīng)的處理。
2、對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();
}
}
}
不幸的是,這個程序也無法執(zhí)行完成,它沒有輸出但卻一直懸在那里,這是為什么那?
JDK文檔中對此有如此的解釋:因為本地的系統(tǒng)對標(biāo)準(zhǔn)輸入和輸出所提供的緩沖池有效,所以錯誤的對標(biāo)準(zhǔn)輸出快速的寫入和從標(biāo)準(zhǔn)輸入快速的讀入都有可能造成子進(jìn)程的鎖,甚至死鎖。
文檔引述完了,作者又開始批評了,他說JDK僅僅說明為什么問題會發(fā)生,卻并沒有說明這個問題怎么解決,這的確是個問題哈。緊接著作者說出自己的做法,就是在執(zhí)行完外部命令后我們要控制好Process的所有輸入和輸出(視情況而定),在這個例子里邊因為調(diào)用的是Javac,而他在沒有參數(shù)的情況下會將提示信息輸出到標(biāo)準(zhǔn)出錯,所以在下面的程序中我們要對此進(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
哎,不管怎么說還是出來了結(jié)果,作者作了一下總結(jié),就是說,為了處理好外部命令大量輸出的情況,你要確保你的程序處理好外部命令所需要的輸入或者輸出。
下一個題目,當(dāng)我們調(diào)用一個我們認(rèn)為是可執(zhí)行程序的時候容易發(fā)生的錯誤(今天晚上我剛剛犯這個錯誤,沒事做這個練習(xí)時候發(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)
說實在的,這個錯誤還真是讓我摸不著頭腦,我覺得在windows中返回2應(yīng)該是沒有找到這個文件的緣故,可能windows 2000中只有cmd命令,dir命令不是當(dāng)前環(huán)境變量能夠解釋的吧。我也不知道了,慢慢往下看吧。
嘿,果然和作者想的一樣,就是因為dir命令是由windows中的解釋器解釋的,直接執(zhí)行dir時無法找到dir.exe這個命令,所以會出現(xiàn)文件未找到這個2的錯誤。如果我們要執(zhí)行這樣的命令,就要先根據(jù)操作系統(tǒng)的不同執(zhí)行不同的解釋程序command.com 或者cmd.exe。
作者對上邊的程序進(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
這里作者教了一個windows中很有用的方法,呵呵,至少我是不知道的,就是cmd.exe /C +一個windows中注冊了后綴的文檔名,windows會自動地調(diào)用相關(guān)的程序來打開這個文檔,我試了一下,的確很好用,但是好像文件路徑中有空格的話就有點問題,我加上引號也無法解決。
這里作者強(qiáng)調(diào)了一下,不要假設(shè)你執(zhí)行的程序是可執(zhí)行的程序,要清楚自己的程序是單獨(dú)可執(zhí)行的還是被解釋的,本章的結(jié)束作者會介紹一個命令行工具來幫助我們分析。
這里還有一點,就是得到process的輸出的方式是getInputStream,這是因為我們要從Java 程序的角度來看,外部程序的輸出對于Java來說就是輸入,反之亦然。
最后的一個漏洞的地方就是錯誤的認(rèn)為exec方法會接受所有你在命令行或者Shell中輸入并接受的字符串。這些錯誤主要出現(xiàn)在命令作為參數(shù)的情況下,程序員錯誤的將所有命令行中可以輸入的參數(shù)命令加入到exec中(這段翻譯的不好,湊合看吧)。下面的例子中就是一個程序員想重定向一個命令的輸出。
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這個輸入重訂向到一個文本文件中,但是這個文件并沒有生成,jecho僅僅是將命令行中的參數(shù)輸出到標(biāo)準(zhǔn)輸出中,用戶覺得可以像dos中重定向一樣將輸出重定向到一個文件中,但這并不能實現(xiàn),用戶錯誤的將exec認(rèn)為是一個shell解釋器,但它并不是,如果你想將一個程序的輸出重定向到其他的程序中,你必須用程序來實現(xiàn)他。可用java.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
這里就不多說了,看看就明白,緊接著作者給出了一個監(jiān)測命令的小程序
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();
}
}
}
對這個程序進(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中是說這不是一個win32程序,這說明路徑中找不到這個網(wǎng)頁的關(guān)聯(lián)程序,下面作者決定用一個絕對路徑來試一下。
E:classescomjavaworldjpitfallsarticle2>java TestExec
"e:program filesnetscapeprogramnetscape.exe e:javadocsindex.html"
ExitValue: 0
好用了,這個我也試了一下,用的是IE。
最后,作者總結(jié)了幾條規(guī)則,防止我們在進(jìn)行Runtime.exec()調(diào)用時出現(xiàn)錯誤。
<!--[if !supportLists]-->1、 <!--[endif]-->在一個外部進(jìn)程執(zhí)行完之前你不能得到他的退出狀態(tài)
<!--[if !supportLists]-->2、 <!--[endif]-->在你的外部程序開始執(zhí)行的時候你必須馬上控制輸入、輸出、出錯這些流。
<!--[if !supportLists]-->3、 <!--[endif]-->你必須用Runtime.exec()去執(zhí)行程序
<!--[if !supportLists]-->4、 <!--[endif]-->你不能象命令行一樣使用Runtime.exec()。
本地文件讀寫編程的基本過程為:
① 生成文件流對象(對文件讀操作時應(yīng)該為FileInputStream類,而文件寫應(yīng)該為FileOutputStream類);
② 調(diào)用FileInputStream或FileOutputStream類中的功能函數(shù)如read()、write(int b)等)讀寫文件內(nèi)容;
③ 關(guān)閉文件(close())。
實例:流文件讀寫
流文件的單元是字節(jié),所以它不但可以讀寫文本文件,也可以讀寫圖片、聲音、影像文件,這種特點非常有用,因為我們可以把這種文件變成流,然后在網(wǎng)絡(luò)上傳輸。
問題是有了通用的流文件以后,為什么還要專門的字符流呢?這是因為文本可以用不同的方式存儲,可以是普通的文本(UTF-8編碼方式),ASCII文本和Unicode文本,字符流對象可以進(jìn)行必要的轉(zhuǎn)換,從而讀出正確的文本。
有人認(rèn)為流文件不能讀寫文本文件,這其實是個誤會,因為文本文件本質(zhì)上也是由字節(jié)組成的,當(dāng)然是流文件的一種。作為讀寫文件的全體,這是沒問題的,但是,如果要處理每次讀入的內(nèi)容,就最好使用字符流。
所以在文本文件處理時,使用字符流是個最常用的方法。
樣例:
import java.io.*;
public class FileStreamDemo {
public static void main(String[] args) throws IOException {
//創(chuàng)建兩個文件,face.gif是已經(jīng)存在文件,newFace.gif是新創(chuàng)建的文件
File inFile = new File("face.gif");
File outFile = new File("newFace.gif");
//創(chuàng)建流文件讀入與寫出類
FileInputStream inStream = new FileInputStream(inFile);
FileOutputStream outStream = new FileOutputStream(outFile);
//通過available方法取得流的最大字符數(shù)
byte[] inOutb = new byte[inStream.available()];
inStream.read(inOutb); //讀入流,保存在byte數(shù)組
outStream.write(inOutb); //寫出流,保存在文件newFace.gif中
inStream.close();
outStream.close();
}
}
實例:讀寫任意大文件應(yīng)用
因為byte數(shù)組最大存儲值不超過64M,所以當(dāng)一個文件大于60M 的時候,需要分開幾個流操作。我們把上面的程序作一個修改,就可以寫入任意大小的文件。這個程序應(yīng)用了FileInputStream類的方法如下:
read(byte[] b,int off,int len)
把特定位置的流內(nèi)容讀入數(shù)組,已經(jīng)讀入byte[]數(shù)組的內(nèi)容,會在流文件中刪除。
程序運(yùn)行的結(jié)果會產(chǎn)生一個新文件。
樣例:
import java.io.*;
public class FileStreamDemo2 {
public static void main(String[] args) throws IOException {
//創(chuàng)建兩個文件
File inFile = new File("tcty36.rm");
File outFile = new File("newtcty36.rm");
//最大的流為60Mb,當(dāng)文件的容量大于60Mb的時候便分開流
final int MAX_BYTE = 60000000;
long streamTotal = 0; //接受流的容量
int streamNum = 0; //流需要分開的數(shù)量
int leave = 0; //文件剩下的字符數(shù)
byte[] inOutb; //byte數(shù)組接受文件的數(shù)據(jù)
//創(chuàng)建流文件讀入與寫出類
FileInputStream inStream = new FileInputStream(inFile);
FileOutputStream outStream = new FileOutputStream(outFile);
//通過available方法取得流的最大字符數(shù)
streamTotal = inStream.available();
//取得流文件需要分開的數(shù)量
streamNum = (int)Math.floor(streamTotal/MAX_BYTE);
//分開文件之后,剩余的數(shù)量
leave = (int)streamTotal % MAX_BYTE;
//文件的容量大于60Mb時進(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); //寫出流
outStream.flush(); //更新寫出的結(jié)果
}
}
//寫出剩下的流數(shù)據(jù)
inOutb = new byte[leave];
inStream.read(inOutb, 0, leave);
outStream.write(inOutb);
outStream.flush();
inStream.close();
outStream.close();
}
}
六、管道PipedInputStream/PipedOutputStream類:
當(dāng)需要在兩個線程中讀寫數(shù)據(jù)的時候,由于線程的并發(fā)執(zhí)行,讀寫的同步問題可能會發(fā)生困難,這時候可以使用管道,管道事實上是一個隊列。
管道是由系統(tǒng)維護(hù)的一個緩沖區(qū),當(dāng)然程序員也可以自己直接指定該緩沖區(qū)的大小(只需要設(shè)置管道流類中的PIPE_SIZE屬性的值)。當(dāng)生產(chǎn)者生產(chǎn)出數(shù)據(jù)后,只需要將數(shù)據(jù)寫入管道中,消費(fèi)者只需要從管道中讀取所需要的數(shù)據(jù)。利用管道的這種機(jī)制,可以將一個線程的輸出結(jié)果直接連接到另一個線程的輸入端口,實現(xiàn)兩者之間的數(shù)據(jù)直接傳送。
線程1
線程2
臨時文件
管道
1.管道的連接:
方法之一是通過構(gòu)造函數(shù)直接將某一個程序的輸出作為另一個程序的輸入,在定義對象時指明目標(biāo)管道對象
PipedInputStream pInput=new PipedInputStream();
PipedOutputStream pOutput= new PipedOutputStream(pInput);
方法之二是利用雙方類中的任一個成員函數(shù) connect()相連接
PipedInputStream pInput=new PipedInputStream();
PipedOutputStream pOutput= new PipedOutputStream();
pinput.connect(pOutput);
2.管道的輸入與輸出:
輸出管道對象調(diào)用write()成員函數(shù)輸出數(shù)據(jù)(即向管道的輸入端發(fā)送數(shù)據(jù));而輸入管道對象調(diào)用read()成員函數(shù)可以讀起數(shù)據(jù)(即從輸出管道中獲得數(shù)據(jù))。這主要是借助系統(tǒng)所提供的緩沖機(jī)制來實現(xiàn)的。
實例:Java的管道的輸入與輸出
import java.io.*;
public class PipedIO //程序運(yùn)行后將sendFile文件的內(nèi)容拷貝到receiverFile文件中
{
public static void main(String args[])
{
try
{
//構(gòu)造讀寫的管道流對象
PipedInputStream pis=new PipedInputStream();
PipedOutputStream pos=new PipedOutputStream();
//實現(xiàn)關(guān)聯(lián)
pos.connect(pis);
//構(gòu)造兩個線程,并且啟動。
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)
{
//寫入管道始端
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
{
//寫文件流對象
FileOutputStream fs=new FileOutputStream(file);
int data;
//從管道末端讀
while((data=pis.read())!=-1)
{
//寫入本地文件
fs.write(data);
}
pis.close();
}
catch(IOException e)
{
System.out.println("Receiver Error" +e);
}
}
}
七、隨機(jī)文件讀寫:RandomAccessFile類
它直接繼承于Object類而非InputStream/OutputStream類,從而可以實現(xiàn)讀寫文件中任何位置中的數(shù)據(jù)(只需要改變文件的讀寫位置的指針)。
編程步驟:
① 生成流對象并且指明讀寫類型;
② 移動讀寫位置;
③ 讀寫文件內(nèi)容;
④ 關(guān)閉文件。
另外由于RandomAccessFile類實現(xiàn)了DataOutput與DataInput接口,因而利用它可以讀寫Java中的不同類型的基本類型數(shù)據(jù)(比如采用readLong()方法讀取長整數(shù),而利用readInt()方法可以讀出整數(shù)值等)。
程序?qū)嵗?#xff1a;
利用隨機(jī)數(shù)據(jù)流RandomAccessFile類來實現(xiàn)記錄用戶在鍵盤的輸入,每執(zhí)行一次,將用戶的鍵盤輸入存儲在指定的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);
}
//讀寫方式可以為"r" or "rw"
RandomAccessFile myFileStream=new RandomAccessFile("c:\\UserInput.txt","rw");
myFileStream.seek(myFileStream.length()) ;
myFileStream.writeBytes(buf.toString());
//將用戶從鍵盤輸入的內(nèi)容添加到文件的尾部
myFileStream.close();
}
catch(IOException e)
{
}
}
}
八、DataInput/DataOutput接口:
實現(xiàn)與機(jī)器無關(guān)的各種數(shù)據(jù)格式讀寫(如readChar() 、readInt()、readLong()、readFloat(),而readLine()將返回一個String)。其中 RandomAccessFile類實現(xiàn)了該接口,具有比FileInputStream或FileOutputStream類更靈活的數(shù)據(jù)讀寫方式。
函數(shù)原型:
#include <sys/stat.h>
int mkdir(const char *path, mode_t mode);
參數(shù):
path是目錄名
mode是目錄權(quán)限
返回值:
返回0 表示成功, 返回 -1表示錯誤,并且會設(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)建了一個newdir目錄,權(quán)限通過ls -al 查看為
drwxr-xr-x
跟用linux命令mkdir創(chuàng)建的目錄權(quán)限位一致。
II. linux下C語言創(chuàng)建多級目錄
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)建一個線程,監(jiān)視某個目錄,一旦目錄里出現(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;
}
//如果這個目錄里 還有目錄,可以在這加判斷
//這里假設(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;
}
Linux支持多種文件系統(tǒng),如ext、ext2、minix、iso9660、msdos、fat、vfat、nfs等。在這些具體文件系統(tǒng)的上層,Linux提供了虛擬文件系統(tǒng)(VFS)來統(tǒng)一它們的行為,虛擬文件系統(tǒng)為不同的文件系統(tǒng)與內(nèi)核的通信提供了一致的接口。
linux下的c語言開發(fā)
在Linux平臺下對文件編程可以使用兩類函數(shù):(1)Linux操作系統(tǒng)文件API;(2)C語言I/O庫函數(shù)。 前者依賴于Linux系統(tǒng)調(diào)用,后者實際上與操作系統(tǒng)是獨(dú)立的,因為在任何操作系統(tǒng)下,使用C語言I/O庫函數(shù)操作文件的方法都是相同的。本章將對這兩種方法進(jìn)行實例講解。
2.Linux文件API
Linux的文件操作API涉及到創(chuàng)建、打開、讀寫和關(guān)閉文件。
創(chuàng)建
int creat(const char *filename, mode_t mode);
參數(shù)mode指定新建文件的存取權(quán)限,它同umask一起決定文件的最終權(quán)限(mode&umask),其中umask代表了文件在創(chuàng)建時需要去掉的一些存取權(quán)限。umask可通過系統(tǒng)調(diào)用umask()來改變:
int umask(int newmask);
該調(diào)用將umask設(shè)置為newmask,然后返回舊的umask,它只影響讀、寫和執(zhí)行權(quán)限。
打開
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
open函數(shù)有兩個形式,其中pathname是我們要打開的文件名(包含路徑名稱,缺省是認(rèn)為在當(dāng)前路徑下面),flags可以去下面的一個值或者是幾個值的組合:
標(biāo)志 含義
O_RDONLY 以只讀的方式打開文件
O_WRONLY 以只寫的方式打開文件
O_RDWR 以讀寫的方式打開文件
O_APPEND 以追加的方式打開文件
O_CREAT 創(chuàng)建一個文件
O_EXEC 如果使用了O_CREAT而且文件已經(jīng)存在,就會發(fā)生一個錯誤
O_NOBLOCK 以非阻塞的方式打開一個文件
O_TRUNC 如果文件已經(jīng)存在,則刪除文件的內(nèi)容
O_RDONLY、O_WRONLY、O_RDWR三個標(biāo)志只能使用任意的一個。
如果使用了O_CREATE標(biāo)志,則使用的函數(shù)是int open(const char *pathname,int flags,mode_t mode); 這個時候我們還要指定mode標(biāo)志,用來表示文件的訪問權(quán)限。mode可以是以下情況的組合:
標(biāo)志 含義
S_IRUSR 用戶可以讀
S_IWUSR 用戶可以寫
S_IXUSR 用戶可以執(zhí)行
S_IRWXU 用戶可以讀、寫、執(zhí)行
S_IRGRP 組可以讀
S_IWGRP 組可以寫
S_IXGRP 組可以執(zhí)行
S_IRWXG 組可以讀寫執(zhí)行
S_IROTH 其他人可以讀
S_IWOTH 其他人可以寫
S_IXOTH 其他人可以執(zhí)行
S_IRWXO 其他人可以讀、寫、執(zhí)行
S_ISUID 設(shè)置用戶執(zhí)行ID
S_ISGID 設(shè)置組的執(zhí)行ID
除了可以通過上述宏進(jìn)行“或”邏輯產(chǎn)生標(biāo)志以外,我們也可以自己用數(shù)字來表示,Linux總共用5個數(shù)字來表示文件的各種權(quán)限:第一位表示設(shè)置用戶ID;第二位表示設(shè)置組ID;第三位表示用戶自己的權(quán)限位;第四位表示組的權(quán)限;最后一位表示其他人的權(quán)限。每個數(shù)字可以取1(執(zhí)行權(quán)限)、2(寫權(quán)限)、4(讀權(quán)限)、0(無)或者是這些值的和。例如,要創(chuàng)建一個用戶可讀、可寫、可執(zhí)行,但是組沒有權(quán)限,其他人可以讀、可以執(zhí)行的文件,并設(shè)置用戶ID位。那么,我們應(yīng)該使用的模式是1(設(shè)置用戶ID)、0(不設(shè)置組 ID)、7(1+2+4,讀、寫、執(zhí)行)、0(沒有權(quán)限)、5(1+4,讀、執(zhí)行)即10705:
open("test", O_CREAT, 10705);
上述語句等價于:
open("test", O_CREAT, S_IRWXU | S_IROTH | S_IXOTH | S_ISUID );
如果文件打開成功,open函數(shù)會返回一個文件描述符,以后對該文件的所有操作就可以通過對這個文件描述符進(jìn)行操作來實現(xiàn)。
讀寫
在文件打開以后,我們才可對文件進(jìn)行讀寫了,Linux中提供文件讀寫的系統(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()實現(xiàn)從文件描述符fd所指定的文件中讀取 length個字節(jié)到buf所指向的緩沖區(qū)中,返回值為實際讀取的字節(jié)數(shù)。函數(shù)write實現(xiàn)將把length個字節(jié)從buf指向的緩沖區(qū)中寫到文件描述符fd所指向的文件中,返回值為實際寫入的字節(jié)數(shù)。
以O(shè)_CREAT為標(biāo)志的open實際上實現(xiàn)了文件創(chuàng)建的功能,因此,下面的函數(shù)等同creat()函數(shù):
int open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
定位
對于隨機(jī)文件,我們可以隨機(jī)的指定位置讀寫,使用如下函數(shù)進(jìn)行定位:
int lseek(int fd, offset_t offset, int whence);
lseek()將文件讀寫指針相對whence移動offset個字節(jié)。操作成功時,返回文件指針相對于文件頭的位置。參數(shù)whence可使用下述值:
SEEK_SET:相對文件開頭
SEEK_CUR:相對文件讀寫指針的當(dāng)前位置
SEEK_END:相對文件末尾
offset可取負(fù)值,例如下述調(diào)用可將文件指針相對當(dāng)前位置向前移動5個字節(jié):
lseek(fd, -5, SEEK_CUR);
由于lseek函數(shù)的返回值為文件指針相對于文件頭的位置,因此下列調(diào)用的返回值就是文件的長度:
lseek(fd, 0, SEEK_END);
關(guān)閉
當(dāng)我們操作完成以后,我們要關(guān)閉文件了,只要調(diào)用close就可以了,其中fd是我們要關(guān)閉的文件描述符:
int close(int fd);
例程:編寫一個程序,在當(dāng)前目錄下創(chuàng)建用戶可讀寫文件“hello.txt”,在其中寫入“Hello, software weekly”,關(guān)閉該文件。再次打開該文件,讀取其中的內(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)建并打開文件 */
if (fd)
{
write(fd, "Hello, Software Weekly", strlen("Hello, software weekly")); /* 寫入 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語言庫函數(shù)
C庫函數(shù)的文件操作實際上是獨(dú)立于具體的操作系統(tǒng)平臺的,不管是在DOS、Windows、Linux還是在VxWorks中都是這些函數(shù):
創(chuàng)建和打開
FILE *fopen(const char *path, const char *mode);
fopen()實現(xiàn)打開指定文件filename,其中的mode為打開模式,C語言中支持的打開模式如下表:
標(biāo)志 含義
r, rb 以只讀方式打開
w, wb 以只寫方式打開。如果文件不存在,則創(chuàng)建該文件,否則文件被截斷
a, ab 以追加方式打開。如果文件不存在,則創(chuàng)建該文件
r+, r+b, rb+ 以讀寫方式打開
w+, w+b, wh+ 以讀寫方式打開。如果文件不存在時,創(chuàng)建新文件,否則文件被截斷
a+, a+b, ab+ 以讀和追加方式打開。如果文件不存在,創(chuàng)建新文件
其中b用于區(qū)分二進(jìn)制文件和文本文件,這一點在DOS、Windows系統(tǒng)中是有區(qū)分的,但Linux不區(qū)分二進(jìn)制文件和文本文件。
讀寫
C庫函數(shù)支持以字符、字符串等為單位,支持按照某中格式進(jìn)行文件的讀寫,這一組函數(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()實現(xiàn)從流stream中讀取加n個字段,每個字段為size字節(jié),并將讀取的字段放入ptr所指的字符數(shù)組中,返回實際已讀取的字段數(shù)。在讀取的字段數(shù)小于num時,可能是在函數(shù)調(diào)用時出現(xiàn)錯誤,也可能是讀到文件的結(jié)尾。所以要通過調(diào)用feof()和ferror()來判斷。
write()實現(xiàn)從緩沖區(qū)ptr所指的數(shù)組中把n個字段寫到流stream中,每個字段長為size個字節(jié),返回實際寫入的字段數(shù)。
另外,C庫函數(shù)還提供了讀寫過程中的定位能力,這些函數(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庫函數(shù)關(guān)閉文件依然是很簡單的操作:
int fclose (FILE *stream);
例程:將第2節(jié)中的例程用C庫函數(shù)來實現(xiàn)。
#include <stdio.h>
#define LENGTH 100
main()
{
FILE *fd;
char str[LENGTH];
fd = fopen("hello.txt", "w+"); /* 創(chuàng)建并打開文件 */
if (fd)
{
fputs("Hello, Software Weekly", fd); /* 寫入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庫函數(shù)。這兩種編程所涉及到文件操作有新建、打開、讀寫和關(guān)閉,對隨機(jī)文件還可以定位。本章對這兩種編程方法都給出了具體的實例。
=>#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
摘要:本文簡單介紹文件操作的三個函數(shù)(open,read,write)的基本用法。
詳細(xì)說明了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ù)說明:
參數(shù) pathname 指向欲打開的文件路徑字符串。下列是參數(shù) flags 所能使用的旗標(biāo):
O_RDONLY 以只讀方式打開文件
O_WRONLY 以只寫方式打開文件
O_RDWR以可讀寫方式打開文件。
上述三種旗標(biāo)是互斥的,也就是不可同時使用,但可與下列的旗標(biāo)利用 OR(|)運(yùn)算符組合。
O_CREAT 若欲打開的文件不存在則自動建立該文件。
O_EXCL 如果 O_CREAT 也被設(shè)置, 此指令會去檢查文件是否存在。文件若不存在則建立該文件,
否則將導(dǎo)致打開文件錯誤。 此外,若 O_CREAT 與 O_EXCL 同時設(shè)置, 并且欲打開的文件為符號連接,則會打開文件失敗。
O_NOCTTY 如果欲打開的文件為終端機(jī)設(shè)備時,則不會將該終端機(jī)當(dāng)成進(jìn)程控制終端機(jī)。
O_TRUNC 若文件存在并且以可寫的方式打開時,此旗標(biāo)會令文件長度清為 0,而原來存于該文件的資料也會消失。
O_APPEND 當(dāng)讀寫文件時會從文件尾開始移動, 也就是所寫入的數(shù)據(jù)會以附加的方式加入到文件后面。
O_NONBLOCK 以不可阻斷的方式打開文件,也就是無論有無數(shù)據(jù)讀取或等待,都會立即返回進(jìn)程之中。
O_NDELAY 同 O_NONBLOCK。
O_SYNC 以同步的方式打開文件。
O_NOFOLLOW 如果參數(shù) pathname 所指的文件為一符號連接,則會令打開文件失敗。
O_DIRECTORY 如果參數(shù) pathname 所指的文件并非為一目錄, 則
會令打開文件失敗。此為 Linux2.2 以后特有的旗標(biāo),以避免一些系
統(tǒng)安全問題。參數(shù) mode 則有下列數(shù)種組合,只有在建立新文件時
才會生效,此外真正建文件時的權(quán)限會受到 umask 值所影響,因此
該文件權(quán)限應(yīng)該為(mode-umaks).
S_IRWXU00700 權(quán)限, 代表該文件所有者具有可讀、 可寫及可執(zhí)行的權(quán)限。
S_IRUSR 或 S_IREAD,00400 權(quán)限,代表該文件所有者具有可讀取的權(quán)限。
S_IWUSR 或 S_IWRITE,00200 權(quán)限,代表該文件所有者具有可寫入的權(quán)限。
S_IXUSR 或 S_IEXEC,00100 權(quán)限,代表該文件所有者具有可執(zhí)行的權(quán)限。
S_IRWXG 00070 權(quán)限,代表該文件用戶組具有可讀、 可寫及可執(zhí)行的權(quán)限。
S_IRGRP 00040 權(quán)限,代表該文件用戶組具有可讀的權(quán)限。
S_IWGRP 00020 權(quán)限,代表該文件用戶組具有可寫入的權(quán)限。
S_IXGRP 00010 權(quán)限,代表該文件用戶組具有可執(zhí)行的權(quán)限。
S_IRWXO 00007 權(quán)限,代表其他用戶具有可讀、可寫及可執(zhí)行的權(quán)限。
S_IROTH 00004 權(quán)限,代表其他用戶具有可讀的權(quán)限
S_IWOTH 00002 權(quán)限,代表其他用戶具有可寫入的權(quán)限。
S_IXOTH 00001 權(quán)限,代表其他用戶具有可執(zhí)行的權(quán)限。
返回值:
若所有欲核查的權(quán)限都通過了檢查則返回 0 值,表示成功,只要有 一個權(quán)限被禁止則返回-1。
錯誤代碼:
EEXIST 參數(shù) pathname 所指的文件已存在,卻使用了 O_CREAT和 O_EXCL 旗標(biāo)
EACCESS 參數(shù) pathname 所指的文件不符合所要求測試的權(quán)限。
EROFS 欲測試寫入權(quán)限的文件存在于只讀文件系統(tǒng)內(nèi)。
EFAULT 參數(shù) pathname 指針超出可存取內(nèi)存空間。
EINVAL 參數(shù) mode 不正確。
ENAMETOOLONG 參數(shù) pathname 太長。
ENOTDIR 參數(shù) pathname 不是目錄。
ENOMEM 核心內(nèi)存不足。
ELOOP 參數(shù) pathname 有過多符號連接問題。
EIO I/O 存取錯誤。
范例:
#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 );//以可讀寫的方式打開一個文件,如果不存在則創(chuàng)建該文件
if ( -1 == fd )
{
printf("Open or create file named \"temp.log\" failed.\n");
return -1;
}
write( fd, s, sizeof(s) );//向該文件中寫入一個字符串
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ù)組中,返回讀取的字符個數(shù)
close( fd );
printf( "%s", buffer );
return 0;
}
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)整會亂碼
in.close();
}catch(Exception e){
e.printStackTrace();
}
myTextView.setText(res);//把得到的內(nèi)容顯示在TextView上
二、 從asset中獲取文件并讀取數(shù)據(jù)(資源文件只能讀不能寫)
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中去讀文件,首先要把文件通過\android-sdk-windows\tools\adb.exe把本地計算機(jī)上的文件copy到sdcard上去,adb.exe push e:/Y.txt /sdcard/, 不可以用adb.exe push e:\Y.txt \sdcard\ 同樣: 把仿真器上的文件copy到本地計算機(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);
//用這個就不行了,必須用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);
四、 寫文件, 一般寫在\data\data\com.test\files\里面,打開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();
}
}
五、 寫, 讀data/data/目錄(相當(dāng)AP工作目錄)上的文件,用openFileOutput
//寫文件在./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;
}
六、 寫, 讀sdcard目錄上的文件,要用FileOutputStream, 不能用openFileOutput
//寫在/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里編譯過的,FileOutputStream是任何文件都可以
參考:http://dev.10086.cn/cmdn/wiki/index.php?doc-view-6017.html
-------------------------------------------------------------
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ī)中用得最廣泛的字符集及其編碼,是由美國國家標(biāo)準(zhǔn)局(ANSI)制定的ASCII碼(American Standard Code for Information Interchange,美國標(biāo)準(zhǔn)信息交換碼),它已被國際標(biāo)準(zhǔn)化組織(ISO)定為國際標(biāo)準(zhǔn),稱為ISO 646標(biāo)準(zhǔn)。適用于所有拉丁文字字母,ASCII碼有7位碼和8位碼兩種形式。
因為1位二進(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)都唯一地編為一個7位的二進(jìn)制碼,對應(yīng)一個字符(或控制碼),這些碼可以排列成一個十進(jìn)制序號0~127。所以,7位 ASCII碼是用七位二進(jìn)制數(shù)進(jìn)行編碼的,可以表示128個字符。
第0~32號及第127號(共34個)是控制字符或通訊專用字符,如控制符:LF(換行)、CR(回車)、FF(換頁)、DEL(刪除)、BEL(振鈴)等;通訊專用字符:SOH(文頭)、EOT(文尾)、ACK(確認(rèn))等;
第33~126號(共94個)是字符,其中第48~57號為0~9十個阿拉伯?dāng)?shù)字;65~90號為26個大寫英文字母,97~122號為26個小寫英文字母,其余為一些標(biāo)點符號、運(yùn)算符號等。
注意:在計算機(jī)的存儲單元中,一個ASCII碼值占一個字節(jié)(8個二進(jìn)制位),其最高位(b7)用作奇偶校驗位。所謂奇偶校驗,是指在代碼傳送過程中用來檢驗是否出現(xiàn)錯誤的一種方法,一般分奇校驗和偶校驗兩種。奇校驗規(guī)定:正確的代碼一個字節(jié)中1的個數(shù)必須是奇數(shù),若非奇數(shù),則在最高位b7添1;偶校驗規(guī)定:正確的代碼一個字節(jié)中1的個數(shù)必須是偶數(shù),若非偶數(shù),則在最高位b7添1。
第128~255號為擴(kuò)展字符(不常用),如需要請下載:完整的8位ASCII字符表
http://code.google.com/p/flying-on-android/
下面的分析都是基于這些源碼的,大家可以下載下來一邊看源碼一邊看文檔。源碼里只要關(guān)注FlyingEvent這個類就可以了。如果只想看一下演示結(jié)果,可以直接把包里的flying放到機(jī)器的/system/bin目錄執(zhí)行,打開logcat后就可以看到演示輸出。運(yùn)行程序時,機(jī)器屏幕會有異象產(chǎn)生,很正常,因為這個程序原本是用于顯示SurfaceFlinger的,這次為了演示EventHub稍微改了一下。大家只要關(guān)注 FlyingEvent.cpp這個文件就好了。
大家也可以用源碼自己編譯出演示程序,只要把解壓后的flying文件夾放到/frameworks/base/cmds/目錄下,然后切換到flying目錄下使用mm編譯。
先大致介紹一下整個流程,再做重點分析。輸入事件流程一共涉及到下面這幾個文件:
/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主要用來讀取設(shè)備文件中的RawEvent,而InputReader.cpp和InputDispatcher.cpp算是它們之間的對接層。
它們的關(guān)系是:WindowManagerService通過InputManager提供的接口開啟一個線程驅(qū)動InputReader不斷地從 /dev/input/目錄下面的設(shè)備文件讀取事件,然后通過InputDispatcher分發(fā)給連接到WindowManagerService服務(wù)的客戶端。
InputReader從設(shè)備文件中讀取的是RawEvent,在交給InputDispatcher進(jìn)行分發(fā)之前,它需要先把RawEvent進(jìn)行轉(zhuǎn)化分類,拆分成KeyEvent、MotionEvent、TrackEvent各種類型等。這篇文章主要關(guān)注的就是這個RawEvent的拆分過程,所以我們的重點在EventHub.cpp中。并且,為了簡單化分析過程,在這里我的分析只關(guān)注觸摸屏事件。看它是如何從RawEvent被拆分成應(yīng)用層用戶事件MotionEvent的。
看下面的分析之前,最好先去上面提到的地址把源碼下載下來,參照里面的FlyingEvent.cpp。
整個過程大致分成這么幾步:
一、初始化。
先new一個EventHub的實例:mEventHub(new EventHub),
接下來,開啟一個線程通過mEventHub不停地從設(shè)備文件中讀取RawEvent并處理:
while (1) {
RawEvent event;
mEventHub->getEvent(&event);
process(event);
}
EventHub在初始化的時候做一些事情,
1、搜索當(dāng)前的輸入設(shè)備每搜索到一個就會產(chǎn)生一個類型為DEVICE_ADDED的事件,當(dāng)讀取這種RawEvent時,InputReader會把搜索到的這個設(shè)備記錄下來。
2、如果搜索到了鍵盤時,就會加載鍵盤布局文件。加載完成后產(chǎn)生一個類型為FINISHED_DEVICE_SCAN的事件。這樣,后邊從驅(qū)動讀取用戶按鍵時,就會去加載的鍵盤布局文件中尋找映射的鍵值封裝成KeyEvent返回給用戶。
二、EventHub初始化完畢后,就開始等待用戶輸入。線程一直阻塞在mEventHub->getEvent(&event),直到有用戶事件產(chǎn)生才會返回。
當(dāng)有一個事件產(chǎn)生時,傳遞給process進(jìn)行處理。
三、事件拆分
FlyingEvent.process里面主要調(diào)用了FlyingEvent.consume方法來處理用戶事件。這里只分析touch事件。touch事件可以分為三種:down,move,up。
down類型的touch事件需要四個RawEvent來完成,第一個是X坐標(biāo)(ABS_X),第二個是Y坐標(biāo)(ABS_Y),第三個代表方向(ABS_PRESSURE)(0的時候是up,1的時候是down,所以這里應(yīng)該是1),第四個是結(jié)束標(biāo)志(SYN_REPORT)。
move類型的touch事件需要三個RawEvent來完成,第一個是X坐標(biāo),第二個是Y坐標(biāo),第三個是結(jié)束標(biāo)志。
up類型的touch事件需要兩個RawEvent來完成,第一個代表方向(0的時候是up,1的時候是down,所以這里應(yīng)該是0),第四個是結(jié)束標(biāo)志。
可能你已經(jīng)注意到了up事件是沒有坐標(biāo)信息的,它的坐標(biāo)信息與down(沒有move時)或最后一個move(down和up之間有move事件產(chǎn)生)事件的坐標(biāo)相同。
從FlyingEvent.consume方法中,每一個事件最終都會生成一個TouchEvent,然后調(diào)用printTouchEvent進(jìn)行打印,最后把它存儲到eventBuffer中。
參考文章
李先靜的“Android輸入事件流程“,不過使用的Android版本比較老了。
http://blog.csdn.net/absurd/archive/2009/05/17/4195363.aspx
(摘自:http://blog.csdn.net/a345017062/article/details/6417929)
svn revert PATH...
描述
恢復(fù)所有對文件和目錄的修改,并且解決所有的沖突狀態(tài)。svn revert不會只是恢復(fù)工作拷貝中一個項目的內(nèi)容,也包括了對屬性修改的恢復(fù)。最終,你可以使用它來取消所有已經(jīng)做過的預(yù)定操作(例如,文件預(yù)定要添加或刪除可以“恢復(fù)”)。
例子
丟棄對一個文件的修改:
$ svn revert foo.c
Reverted foo.c
如果你希望恢復(fù)一整個目錄的文件,可以使用--recursive選項:
$ svn revert --recursive .
Reverted newdir/afile
Reverted foo.c
Reverted bar.txt
2.還原到以前版本
svn update -r 200 test.php(將版本庫中的文件test.php還原到版本200)
3.列出本地與SVN當(dāng)前版本差異
svn status -v path(顯示文件和子目錄狀態(tài))
簡寫:svn st
第一列保持相同,第二列顯示工作版本號,第三和第四列顯示最后一次修改的版本號和修改人。
另外,可執(zhí)行script -q tty.log后,就開始記錄終端的輸入輸出信息,結(jié)束的時候按ctrl+D即可得到終端的內(nèi)容文件tty.log
4. svn比較差異
svn diff path(將修改的文件與基礎(chǔ)版本比較)
例如:svn diff test.php
svn diff -r m:n path(對版本m和版本n比較差異)
注:svn status、svn diff和 svn revert這三條命令在沒有網(wǎng)絡(luò)的情況下也可以執(zhí)行的,原因是svn在本地的.svn中保留了本地版本的原始拷貝。
[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
下面是對這些數(shù)值的解釋:
total:總計物理內(nèi)存的大小。
used:已使用多大。
free:可用有多少。
Shared:多個進(jìn)程共享的內(nèi)存總額。
Buffers/cached:磁盤緩存的大小。
第三行(-/+ buffers/cached):
used:已使用多大。
free:可用有多少。
第四行就不多解釋了。
區(qū)別:第二行(mem)的used/free與第三行(-/+ buffers/cache) used/free的區(qū)別。 這兩個的區(qū)別在于使用的角度來看,第一行是從OS的角度來看,因為對于OS,buffers/cached 都是屬于被使用,所以他的可用內(nèi)存是16176KB,已用內(nèi)存是3250004KB,其中包括,內(nèi)核(OS)使用+Application(X, oracle,etc)使用的+buffers+cached.
第三行所指的是從應(yīng)用程序角度來看,對于應(yīng)用程序來說,buffers/cached 是等于可用的,因為buffer/cached是為了提高文件讀取的性能,當(dāng)應(yīng)用程序需在用到內(nèi)存的時候,buffer/cached會很快地被回收。
所以從應(yīng)用程序的角度來說,可用內(nèi)存=系統(tǒng)free memory+buffers+cached。
如上例:
2795064=16176+110652+2668236
接下來解釋什么時候內(nèi)存會被交換,以及按什么方交換。 當(dāng)可用內(nèi)存少于額定值的時候,就會開會進(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)存的測量
測量一個進(jìn)程占用了多少內(nèi)存,linux為我們提供了一個很方便的方法,/proc目錄為我們提供了所有的信息,實際上top等工具也通過這里來獲取相應(yīng)的信息。
/proc/meminfo 機(jī)器的內(nèi)存使用信息
/proc/pid/maps pid為進(jìn)程號,顯示當(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。。。的每行的每個參數(shù)意思(以第一行為例)為:
參數(shù) 解釋 /proc//status
Size (pages) 任務(wù)虛擬地址空間的大小 VmSize/4
Resident(pages) 應(yīng)用程序正在使用的物理內(nèi)存的大小 VmRSS/4
Shared(pages) 共享頁數(shù) 0
Trs(pages) 程序所擁有的可執(zhí)行虛擬內(nèi)存的大小 VmExe/4
Lrs(pages) 被映像到任務(wù)的虛擬內(nèi)存空間的庫的大小 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
我們通過free命令查看機(jī)器空閑內(nèi)存時,會發(fā)現(xiàn)free的值很小。這主要是因為,在linux中有這么一種思想,內(nèi)存不用白不用,因此它盡可能的cache和buffer一些數(shù)據(jù),以方便下次使用。但實際上這些內(nèi)存也是可以立刻拿來使用的。
所以 空閑內(nèi)存=free+buffers+cached=total-used
1:新建一個目標(biāo),在此目錄下準(zhǔn)備好需要的文件,如system目錄文件、boot.img、recovery.img等.
mkdir testupdate
cp system/ testupdate/ -tf
注:如果文件是system.img鏡像可以用unyaffs解壓出來得到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)修改些腳本
說明:system是要更新的目錄,android-info.txt是板的版本信息,update-script是輸出文件名
3:建立一個目錄名稱為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根目錄下去驗證吧!
注意:
1)如果文件里有連接,應(yīng)該在獲取update-script之后在原文件里刪除鏈接文件,再打包,否則symlink將出錯;
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
這里需要驗證哪個能用android寫下去
三: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)部分時候可以如第四所示范
2:如果recovery為ramdisk形式
=============================================
制 作ramdisk的過程。
1.在/mnt下創(chuàng)建rdmnt 和 rdimg 目錄
mkdir rdmnt
mkdir rdimg
2.創(chuàng)建一個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
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
但令人遺憾的是,在許多講述linux應(yīng)用的書籍上都沒有詳細(xì)介紹這個功能強(qiáng)大但又非常復(fù)雜的編譯工具。在這里我就向大家詳細(xì)介紹一下make及其描述文件makefile。
Makefile文件
Make工具最主要也是最基本的功能就是通過makefile文件來描述源程序之間的相互關(guān)系并自動維護(hù)編譯工作。而makefile 文件需要按照某種語法進(jìn)行編寫,文件中需要說明如何編譯各個源文件并連接生成可執(zhí)行文件,并要求定義源文件之間的依賴關(guān)系。makefile 文件是許多編譯器--包括 Windows NT 下的編譯器--維護(hù)編譯信息的常用方法,只是在集成開發(fā)環(huán)境中,用戶通過友好的界面修改 makefile 文件而已。
在 UNIX 系統(tǒng)中,習(xí)慣使用 Makefile 作為 makfile 文件。如果要使用其他文件作為 makefile,則可利用類似下面的 make 命令選項指定 makefile 文件:
$ make -f Makefile.debug
例如,一個名為prog的程序由三個C源文件filea.c、fileb.c和filec.c以及庫文件LS編譯生成,這三個文件還分別包含自己的頭文件a.h 、b.h和c.h。通常情況下,C編譯器將會輸出三個目標(biāo)文件filea.o、fileb.o和filec.o。假設(shè)filea.c和fileb.c都要聲明用到一個名為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
----------------------------------------------------------
這個描述文檔就是一個簡單的makefile文件。
從上面的例子注意到,第一個字符為 # 的行為注釋行。第一個非注釋行指定prog由三個目標(biāo)文件filea.o、fileb.o和filec.o鏈接生成。第三行描述了如何從prog所依賴的文件建立可執(zhí)行文件。接下來的4、6、8行分別指定三個目標(biāo)文件,以及它們所依賴的.c和.h文件以及defs文件。而5、7、9行則指定了如何從目標(biāo)所依賴的文件建立目標(biāo)。
當(dāng)filea.c或a.h文件在編譯之后又被修改,則 make 工具可自動重新編譯filea.o,如果在前后兩次編譯之間,filea.C 和a.h 均沒有被修改,而且 test.o 還存在的話,就沒有必要重新編譯。這種依賴關(guān)系在多源文件的程序編譯中尤其重要。通過這種依賴關(guān)系的定義,make 工具可避免許多不必要的編譯工作。當(dāng)然,利用 Shell 腳本也可以達(dá)到自動編譯的效果,但是,Shell 腳本將全部編譯任何源文件,包括哪些不必要重新編譯的源文件,而 make 工具則可根據(jù)目標(biāo)上一次編譯的時間和目標(biāo)所依賴的源文件的更新時間而自動判斷應(yīng)當(dāng)編譯哪個源文件。
Makefile文件作為一種描述文檔一般需要包含以下內(nèi)容:
◆ 宏定義
◆ 源文件之間的相互依賴關(guān)系
◆ 可執(zhí)行的命令
Makefile中允許使用簡單的宏指代源文件及其相關(guān)編譯信息,在linux中也稱宏為變量。在引用宏時只需在變量前加$符號,但值得注意的是,如果變量名的長度超過一個字符,在引用時就必須加圓括號()。
下面都是有效的宏引用:
$(CFLAGS)
$2
$Z
$(Z)
其中最后兩個引用是完全一致的。
需要注意的是一些宏的預(yù)定義變量,在Unix系統(tǒng)中,$*、$@、$?和$<四個特殊宏的值在執(zhí)行命令的過程中會發(fā)生相應(yīng)的變化,而在GNU make中則定義了更多的預(yù)定義變量。關(guān)于預(yù)定義變量的詳細(xì)內(nèi)容,
宏定義的使用可以使我們脫離那些冗長乏味的編譯選項,為編寫makefile文件帶來很大的方便。
---------------------------------------------------------
# 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
……
---------------------------------------------------------
此時如果執(zhí)行不帶參數(shù)的make命令,將連接三個目標(biāo)文件和庫文件LS;但是如果在make命令后帶有新的宏定義:
make "LIBES= -LL -LS"
則命令行后面的宏定義將覆蓋makefile文件中的宏定義。若LL也是庫文件,此時make命令將連接三個目標(biāo)文件以及兩個庫文件LS和LL。
在Unix系統(tǒng)中沒有對常量NULL作出明確的定義,因此我們要定義NULL字符串時要使用下述宏定義:
STRINGNAME=
Make命令
在make命令后不僅可以出現(xiàn)宏定義,還可以跟其他命令行參數(shù),這些參數(shù)指定了需要編譯的目標(biāo)文件。其標(biāo)準(zhǔn)形式為:
target1 [target2 …]:[:][dependent1 …][;commands][#…]
[(tab) commands][#…]
方括號中間的部分表示可選項。Targets和dependents當(dāng)中可以包含字符、數(shù)字、句點和"/"符號。除了引用,commands中不能含有"#",也不允許換行。
在通常的情況下命令行參數(shù)中只含有一個":",此時command序列通常和makefile文件中某些定義文件間依賴關(guān)系的描述行有關(guān)。如果與目標(biāo)相關(guān)連的那些描述行指定了相關(guān)的command序列,那么就執(zhí)行這些相關(guān)的command命令,即使在分號和(tab)后面的aommand字段甚至有可能是NULL。如果那些與目標(biāo)相關(guān)連的行沒有指定command,那么將調(diào)用系統(tǒng)默認(rèn)的目標(biāo)文件生成規(guī)則。
如果命令行參數(shù)中含有兩個冒號"::",則此時的command序列也許會和makefile中所有描述文件依賴關(guān)系的行有關(guān)。此時將執(zhí)行那些與目標(biāo)相關(guān)連的描述行所指向的相關(guān)命令。同時還將執(zhí)行build-in規(guī)則。
如果在執(zhí)行command命令時返回了一個非"0"的出錯信號,例如makefile文件中出現(xiàn)了錯誤的目標(biāo)文件名或者出現(xiàn)了以連字符打頭的命令字符串,make操作一般會就此終止,但如果make后帶有"-i"參數(shù),則make將忽略此類出錯信號。
Make命本身可帶有四種參數(shù):標(biāo)志、宏定義、描述文件名和目標(biāo)文件名。其標(biāo)準(zhǔn)形式為:
Make [flags] [macro definitions] [targets]
Unix系統(tǒng)下標(biāo)志位flags選項及其含義為:
-f file 指定file文件為描述文件,如果file參數(shù)為"-"符,那么描述文件指向標(biāo)準(zhǔn)輸入。如果沒有"-f"參數(shù),則系統(tǒng)將默認(rèn)當(dāng)前目錄下名為 makefile或者名為Makefile的文件為描述文件。在linux中, GNU make 工具在當(dāng)前工作目錄中按照GNUmakefile、makefile、Makefile的順序搜索 makefile文件。
-i 忽略命令執(zhí)行返回的出錯信息。
-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)文件和檢測時間的詳細(xì)信息。
linux下make標(biāo)志位的常用選項與Unix系統(tǒng)中稍有不同,下面我們只列出了不同部分:
-c dir 在讀取 makefile 之前改變到指定的目錄dir。
-I dir 當(dāng)包含其他 makefile文件時,利用該選項指定搜索目錄。
-h help文擋,顯示所有的make選項。
-w 在處理 makefile 之前和之后,都顯示工作目錄。
通過命令行參數(shù)中的target ,可指定make要編譯的目標(biāo),并且允許同時定義編譯多個目標(biāo),操作時按照從左向右的順序依次編譯target選項中指定的目標(biāo)文件。如果命令行中沒有指定目標(biāo),則系統(tǒng)默認(rèn)target指向描述文件中第一個目標(biāo)文件。
通常,makefile 中還定義有 clean 目標(biāo),可用來清除編譯過程中的中間文件,例如:
clean:
rm -f *.o
運(yùn)行 make clean 時,將執(zhí)行 rm -f *.o 命令,最終刪除所有編譯過程中產(chǎn)生的所有中間文件。
隱含規(guī)則
在make 工具中包含有一些內(nèi)置的或隱含的規(guī)則,這些規(guī)則定義了如何從不同的依賴文件建立特定類型的目標(biāo)。Unix系統(tǒng)通常支持一種基于文件擴(kuò)展名即文件名后綴的隱含規(guī)則。這種后綴規(guī)則定義了如何將一個具有特定文件名后綴的文件(例如.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源語法
.l Lex源語法
在早期的Unix系統(tǒng)系統(tǒng)中還支持Yacc-C源語法和Lex源語法。在編譯過程中,系統(tǒng)會首先在makefile文件中尋找與目標(biāo)文件相關(guān)的.C文件,如果還有與之相依賴的.y和.l文件,則首先將其轉(zhuǎn)換為.c文件后再編譯生成相應(yīng)的.o文件;如果沒有與目標(biāo)相關(guān)的.c文件而只有相關(guān)的.y文件,則系統(tǒng)將直接編譯.y文件。
而GNU make 除了支持后綴規(guī)則外還支持另一種類型的隱含規(guī)則--模式規(guī)則。這種規(guī)則更加通用,因為可以利用模式規(guī)則定義更加復(fù)雜的依賴性規(guī)則。模式規(guī)則看起來非常類似于正則規(guī)則,但在目標(biāo)名稱的前面多了一個 % 號,同時可用來定義目標(biāo)和依賴文件之間的關(guān)系,例如下面的模式規(guī)則定義了如何將任意一個 file.c 文件轉(zhuǎn)換為 file.o 文件:
%.c:%.o
$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
#EXAMPLE#
下面將給出一個較為全面的示例來對makefile文件和make命令的執(zhí)行進(jìn)行進(jìn)一步的說明,其中make命令不僅涉及到了C源文件還包括了Yacc 語法。本例選自"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é)果而沒有相應(yīng)的命令行,是因為"@size make"命令以"@"起始,這個符號禁止打印輸出它所在的命令行。
描述文件中的最后幾條命令行在維護(hù)編譯信息方面非常有用。其中"print"命令行的作用是打印輸出在執(zhí)行過上次"make print"命令后所有改動過的文件名稱。系統(tǒng)使用一個名為print的0字節(jié)文件來確定執(zhí)行print命令的具體時間,而宏$?則指向那些在print 文件改動過之后進(jìn)行修改的文件的文件名。如果想要指定執(zhí)行print命令后,將輸出結(jié)果送入某個指定的文件,那么就可修改P的宏定義:
make print "P= cat>zap"
在linux中大多數(shù)軟件提供的是源代碼,而不是現(xiàn)成的可執(zhí)行文件,這就要求用戶根據(jù)自己系統(tǒng)的實際情況和自身的需要來配置、編譯源程序后,軟件才能使用。只有掌握了make工具,才能讓我們真正享受到到Linux這個自由軟件世界的帶給我們無窮樂趣。
另一篇,http://wiki.ubuntu.org.cn/%E8%B7%9F%E6%88%91%E4%B8%80%E8%B5%B7%E5%86%99Makefile
在編譯源代碼之前通常需要在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
}
會依次進(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)選擇以后會出現(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)過:
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 \
))
怎樣添加一個模塊
LOCAL_PATH:= $(call my-dir)
#編譯靜態(tài)庫
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)
#編譯動態(tài)庫
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)庫
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)
#使用動態(tài)庫
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)對象
LOCAL_SRC_FILES - 編譯的源文件
LOCAL_C_INCLUDES - 需要包含的頭文件目錄
LOCAL_SHARED_LIBRARIES - 鏈接時需要的外部庫
LOCAL_PRELINK_MODULE - 是否需要prelink處理
BUILD_SHARED_LIBRARY - 指明要編譯成動態(tài)庫
LOCAL_PATH - 編譯時的目錄
$(call 目錄,目錄….) 目錄引入操作符
如該目錄下有個文件夾名稱 src,則可以這樣寫 $(call src),那么就會得到 src 目錄的完整路徑
include $(CLEAR_VARS) -清除之前的一些系統(tǒng)變量
CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mk
在 build/core/config.mk 定義 CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mk
通過include 包含自定義的.mk文件(即是自定義編譯規(guī)則)或是引用系統(tǒng)其他的.mk文件(系統(tǒng)定義的編譯規(guī)則)。
LOCAL_SRC_FILES - 編譯的源文件
可以是.c, .cpp, .java, .S(匯編文件)或是.aidl等格式
不同的文件用空格隔開。如果編譯目錄子目錄,采用相對路徑,如子目錄/文件名。也可以通過$(call 目錄),指明編譯某目錄
下所有.c/.cpp/.java/.S/ .aidl文件.追加文件 LOCAL_SRC_FILES += 文件
LOCAL_C_INCLUDES - 需要包含的頭文件目錄
可以是系統(tǒng)定義路徑,也可以是相對路徑. 如該編譯目錄下有個include目錄,寫法是include/*.h
LOCAL_SHARED_LIBRARIES - 鏈接時需要的外部共享庫
LOCAL_STATIC_LIBRARIES - 鏈接時需要的外部外部靜態(tài)
LOCAL_JAVA_LIBRARIES 加入jar包
LOCAL_MODULE - 編譯的目標(biāo)對象
module 是指系統(tǒng)的 native code,通常針對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 - 指明要編譯成動態(tài)庫。
編譯的目標(biāo),用include 操作符
UILD_STATIC_LIBRARY來指明要編譯成靜態(tài)庫。
如果是java文件的話,會用到系統(tǒng)的編譯腳本host_java_library.mk,用BUILD_PACKAGE來指明。三個編譯
-------------------
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庫
./build/core/config.mk:59:BUILD_STATIC_JAVA_LIBRARY:= $(BUILD_SYSTEM)/static_java_library.mk
------------------
BUILD_HOST_JAVA_LIBRARY 編譯本機(jī)用的JAVA庫
./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)行時鏈接的方法來加速共享庫的加載,它不僅可以加快起動速度,還可以減少部分內(nèi)存開銷,
是各種Linux架構(gòu)上用于減少程序加載時間、縮短系統(tǒng)啟動時間和加快應(yīng)用程序啟動的很受歡迎的一個工具。程序運(yùn)行時的
動態(tài)鏈接尤其是重定位(relocation)的開銷對于大型系統(tǒng)來說是很大的。
動態(tài)鏈接和加載的過程開銷很大,并且在大多數(shù)的系統(tǒng)上, 函數(shù)庫并不會常常被更動, 每次程序被執(zhí)行時所進(jìn)行的鏈接
動作都是完全相同的,對于嵌入式系統(tǒng)來說尤其如此。因此,這一過程可以改在運(yùn)行時之前就可以預(yù)先處理好,即花一些時間
利用Prelink工具對動態(tài)共享庫和可執(zhí)行文件進(jìn)行處理,修改這些二進(jìn)制文件并加入相應(yīng)的重定位等信息,節(jié)約了本來在程序
啟動時的比較耗時的查詢函數(shù)地址等工作,這樣可以減少程序啟動的時間,同時也減少了內(nèi)存的耗用。
Prelink的這種做法當(dāng)然也有代價:每次更新動態(tài)共享庫時,相關(guān)的可執(zhí)行文件都需要重新執(zhí)行一遍Prelink才能保
證有效,因為新的共享庫中的符號信息、地址等很可能與原來的已經(jīng)不同了,這就是為什么 android framework代碼一改動,
這時候就會導(dǎo)致相關(guān)的應(yīng)用程序重新被編譯。
這種代價對于嵌入式系統(tǒng)的開發(fā)者來說可能稍微帶來一些復(fù)雜度,不過好在對用戶來說幾乎是可以忽略的。
--------------------
變量設(shè)置為false那么將不做prelink操作
LOCAL_PRELINK_MODULE := false
默認(rèn)是需要prlink的,同時需要在 build/core/prelink-linux-arm.map 中加入
libhellod.so 0x96000000
這個map文件好像是制定動態(tài)庫的地址的,在前面注釋上面有一些地址范圍的信息,注意庫與庫之間的間隔數(shù),
如果指定不好的話編譯的時候會提示說地址空間沖突的問題。另外,注意排序,這里要把數(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”
參考文檔:
動態(tài)庫優(yōu)化——Prelink(預(yù)連接)技術(shù)
http://www.eefocus.com/article/09-04/71629s.html
===============
LOCAL_ARM_MODE := arm
目前Android大部分都是基于Arm處理器的,Arm指令用兩種模式Thumb(每條指令兩個字節(jié))和arm指令(每條指令四個字節(jié))
LOCAL_CFLAGS += -O3 -fstrict-aliasing -fprefetch-loop-arrays
通過設(shè)定編譯器操作,優(yōu)化級別,-O0表示沒有優(yōu)化,-O1為缺省值,-O3優(yōu)化級別最高
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
android list targets
2. 顯示系統(tǒng)中全部AVD(模擬器):
android list avd
3. 創(chuàng)建AVD(模擬器):
android create avd --name 名稱 --target 平臺編號
4. 啟動模擬器:
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. 啟動DDMS:
ddms
9. 顯示當(dāng)前運(yùn)行的全部模擬器:
adb devices
10. 對某一模擬器執(zhí)行命令:
abd -s 模擬器編號 命令
11. 安裝應(yīng)用程序:
adb install -r 應(yīng)用程序.apk
12. 獲取模擬器中的文件:
adb pull <remote> <local>
13. 向模擬器中寫文件:
adb push <local> <remote>
14. 進(jìn)入模擬器的shell模式:
adb shell
15. 啟動SDK,文檔,實例下載管理器:
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后面跟的命令主要來自:
源碼\system\core\toolbox目錄和源碼\frameworks\base\cmds目錄。
20. 刪除系統(tǒng)應(yīng)用:
adb remount (重新掛載系統(tǒng)分區(qū),使系統(tǒng)分區(qū)重新可寫)。
adb shell
cd system/app
rm *.apk
21. 獲取管理員權(quán)限:
adb root
22. 啟動Activity:
adb shell am start -n 包名/包名+類名(-n 類名,-a action,-d date,-m MIME-TYPE,-c category,-e 擴(kuò)展數(shù)據(jù),等)。
23、發(fā)布端口:
你可以設(shè)置任意的端口號,做為主機(jī)向模擬器或設(shè)備的請求端口。如:
adb forward tcp:5555 tcp:8000
24、復(fù)制文件:
你可向一個設(shè)備或從一個設(shè)備中復(fù)制文件,
復(fù)制一個文件或目錄到設(shè)備或模擬器上:
adb push <source> <destination></destination></source>
如:adb push test.txt /tmp/test.txt
從設(shè)備或模擬器上復(fù)制一個文件或目錄:
adb pull <source> <destination></destination></source>
如:adb pull /addroid/lib/libwebcore.so .
25、搜索模擬器/設(shè)備的實例:
取得當(dāng)前運(yùn)行的模擬器/設(shè)備的實例的列表及每個實例的狀態(tài):
adb devices
26、查看bug報告:
adb bugreport
27、記錄無線通訊日志:
一般來說,無線通訊的日志非常多,在運(yùn)行時沒必要去記錄,但我們還是可以通過命令,設(shè)置記錄:
adb shell
logcat -b radio
28、獲取設(shè)備的ID和序列號:
adb get-product
adb get-serialno
29、訪問數(shù)據(jù)庫SQLite3
adb shell
sqlite3
busybox
BusyBox 是標(biāo)準(zhǔn) Linux 工具的一個單個可執(zhí)行實現(xiàn)。BusyBox 包含了一些簡單的工具,例如 cat 和 echo,還包含了一些更大、更復(fù)雜的工具,例如 grep、find、mount 以及 telnet。有些人將 BusyBox 稱為 Linux 工具里的瑞士軍刀.簡單的說BusyBox就好像是個大工具箱,它集成壓縮了 Linux 的許多工具和命令。
1、 BusyBox 的誕生
BusyBox 最初是由 Bruce Perens 在 1996 年為 Debian GNU/Linux 安裝盤編寫的。其目標(biāo)是在一張軟盤上創(chuàng)建一個可引導(dǎo)的 GNU/Linux 系統(tǒng),這可以用作安裝盤和急救盤。
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)行這三個鏈接:
#./ls
#./rm
#./mkdir
就可以分別完成了ls rm 和mkdir命令的功能.雖然他們都指向同一個可執(zhí)行程序busybox,但是只要鏈接名不同,完成的功能就不同,很多l(xiāng)inux網(wǎng)站都提供busybox的源代碼下載。
3、配置busybox
busybox的配置程序和linux內(nèi)核菜單配置方式簡直一模一樣.熟悉用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的功能選項。
General Configuration應(yī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)
這個選項是一定要選擇的,這樣才能把busybox編譯成靜態(tài)鏈接的可執(zhí)行文件,運(yùn)行時才獨(dú)立于其他函數(shù)庫.否則必需要其他庫文件才能運(yùn)行,在單一個linux內(nèi)核不能使它正常工作.
Installation Options
Don't use /usr
這個選項也一定要選,否則make install 后busybox將安裝在原系統(tǒng)的/usr下,這將覆蓋掉系統(tǒng)原有的命令.選擇這個選項后,make install后會在busybox目錄下生成一個叫_install的目錄,里面有busybox和指向它的鏈接.
其它選項都是一些linux基本命令選項,自己需要哪些命令就編譯進(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目錄下,其他的都是指向他的符號鏈接.
Android系統(tǒng)在超級終端下必會的命令大全(二)
一、安裝和登錄命令
reboot
1.作用
reboot命令的作用是重新啟動計算機(jī),它的使用權(quán)限是系統(tǒng)管理者。
2.格式
reboot [-n] [-w] [-d] [-f] [-i]
3.主要參數(shù)
-n: 在重開機(jī)前不做將記憶體資料寫回硬盤的動作。
-w: 并不會真的重開機(jī),只是把記錄寫到/var/log/wtmp文件里。
-d: 不把記錄寫到/var/log/wtmp文件里(-n這個參數(shù)包含了-d)。
-i: 在重開機(jī)之前先把所有與網(wǎng)絡(luò)相關(guān)的裝置停止。
mount
1.作用
mount命令的作用是加載文件系統(tǒng),它的用權(quán)限是超級用戶或/etc/fstab中允許的使用者。
2.格式
mount -a [-fv] [-t vfstype] [-n] [-rw] [-F] device dir
3.主要參數(shù)
-h:顯示輔助信息。
-v:顯示信息,通常和-f用來除錯。
-a:將/etc/fstab中定義的所有文件系統(tǒng)掛上。
-F:這個命令通常和-a一起使用,它會為每一個mount的動作產(chǎn)生一個行程負(fù)責(zé)執(zhí)行。在系統(tǒng)需要掛上大量NFS文件系統(tǒng)時可以加快加載的速度。
-f:通常用于除錯。它會使mount不執(zhí)行實際掛上的動作,而是模擬整個掛上的過程,通常會和-v一起使用。
-t vfstype:顯示被加載文件系統(tǒng)的類型。
-n:一般而言,mount掛上后會在/etc/mtab中寫入一筆資料,在系統(tǒng)中沒有可寫入文件系統(tǒng)的情況下,可以用這個選項取消這個動作。
4.應(yīng)用技巧
在 Linux和Unix系統(tǒng)上,所有文件都是作為一個大型樹(以/為根)的一部分訪問的。要訪問CD-ROM上的文件,需要將CD-ROM設(shè)備掛裝在文件樹中的某個掛裝點。如果發(fā)行版安裝了自動掛裝包,那么這個步驟可自動進(jìn)行。在Linux中,如果要使用硬盤、光驅(qū)等儲存設(shè)備,就得先將它加載,當(dāng)儲存設(shè)備掛上了之后,就可以把它當(dāng)成一個目錄來訪問。掛上一個設(shè)備使用mount命令。在使用mount這個指令時,至少要先知道下列三種信息:要加載對象的文件系統(tǒng)類型、要加載對象的設(shè)備名稱及要將設(shè)備加載到哪個目錄下。
(1)Linux可以識別的文件系統(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光盤用的文件系統(tǒng):iso9660。
雖然vfat是指FAT 32系統(tǒng),但事實上它也兼容FAT 16的文件系統(tǒng)類型。
(2)確定設(shè)備的名稱
在Linux中,設(shè)備名稱通常都存在/dev里。這些設(shè)備名稱的命名都是有規(guī)則的,可以用“推理”的方式把設(shè)備名稱找出來。例如,/dev/hda1這個
IDE設(shè)備,hd是Hard Disk(硬盤)的,sd是SCSI Device,fd是Floppy Device(或是Floppy
Disk?)。a代表第一個設(shè)備,通常IDE接口可以接上4個IDE設(shè)備(比如4塊硬盤)。所以要識別IDE硬盤的方法分別就是hda、hdb、hdc、
hdd。hda1中的“1”代表hda的第一個硬盤分區(qū)
(partition),hda2代表hda的第二主分區(qū),第一個邏輯分區(qū)從hda5開始,依此類推。此外,可以直接檢查/var/log/messages文件,在該文件中可以找到計算機(jī)開機(jī)后系統(tǒng)已辨認(rèn)出來的設(shè)備代號。
(3)查找掛接點
在決定將設(shè)備掛接之前,先要查看一下計算機(jī)是不是有個/mnt的空目錄,該目錄就是專門用來當(dāng)作掛載點(MountPoint)的目錄。建議在/mnt里建幾個/mnt/cdrom、/mnt/floppy、/mnt/mo等目錄,當(dāng)作目錄的專用掛載點。舉例而言,如要掛載下列5個設(shè)備,其執(zhí)行指令可能如下 (假設(shè)都是Linux的ext2系統(tǒng),如果是Windows XX請將ext2改成vfat):
軟盤 ===>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
不過目前大多數(shù)較新的Linux發(fā)行版本(包括紅旗 Linux、中軟Linux、Mandrake Linux等)都可以自動掛裝文件系統(tǒng),但Red Hat Linux除外。
umount
1.作用
umount命令的作用是卸載一個文件系統(tǒng),它的使用權(quán)限是超級用戶或/etc/fstab中允許的使用者。
2.格式
unmount -a [-fFnrsvw] [-t vfstype] [-n] [-rw] [-F] device dir
3.使用說明
umount
命令是mount命令的逆操作,它的參數(shù)和使用方法和mount命令是一樣的。Linux掛裝CD-ROM后,會鎖定CD—ROM,這樣就不能用CD-
ROM面板上的Eject按鈕彈出它。但是,當(dāng)不再需要光盤時,如果已將/cdrom作為符號鏈接,請使用umount/cdrom來卸裝它。僅當(dāng)無用戶
正在使用光盤時,該命令才會成功。該命令包括了將帶有當(dāng)前工作目錄當(dāng)作該光盤中的目錄的終端窗口。
exit
1.作用
exit命令的作用是退出系統(tǒng),它的使用權(quán)限是所有用戶。
2.格式
exit
3.參數(shù)
exit命令沒有參數(shù),運(yùn)行后退出系統(tǒng)進(jìn)入登錄界面。
--------------------------------------------------------------------------------
作者: ☆-☆ 時間: 2010-6-8 11:52
Android系統(tǒng)在超級終端下必會的命令大全(三)
二、文件處理命令
mkdir
1.作用
mkdir命令的作用是建立名稱為dirname的子目錄,與MS DOS下的md命令類似,它的使用權(quán)限是所有用戶。
2.格式
mkdir [options] 目錄名
3.[options]主要參數(shù)
-m, --mode=模式:設(shè)定權(quán)限,與chmod類似。
-p, --parents:需要時創(chuàng)建上層目錄;如果目錄早已存在,則不當(dāng)作錯誤。
-v, --verbose:每次創(chuàng)建新目錄都顯示信息。
--version:顯示版本信息后離開。
4.應(yīng)用實例
在進(jìn)行目錄創(chuàng)建時可以設(shè)置目錄的權(quán)限,此時使用的參數(shù)是“-m”。假設(shè)要創(chuàng)建的目錄名是“tsk”,讓所有用戶都有rwx(即讀、寫、執(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:只輸出匹配行的計數(shù)。
-I:不區(qū)分大小寫(只適用于單字符)。
-h:查詢多文件時不顯示文件名。
-l:查詢多文件時只輸出包含匹配字符的文件名。
-n:顯示匹配行及行號。
-s:不顯示不存在或無匹配文本的錯誤信息。
-v:顯示不包含匹配文本的所有行。
pattern正則表達(dá)式主要參數(shù):
\:忽略正則表達(dá)式中特殊字符的原有含義。
^:匹配正則表達(dá)式的開始行。
$: 匹配正則表達(dá)式的結(jié)束行。
\:到匹配正則表達(dá)式的行結(jié)束。
[ ]:單個字符,如[A]即A符合要求 。
[ - ]:范圍,如[A-Z],即A、B、C一直到Z都符合要求 。
。:所有的單個字符。
* :有字符,長度可以為0。
正則表達(dá)式是Linux/Unix系統(tǒng)中非常重要的概念。正則表達(dá)式(也稱為“regex”或“regexp”)是一個可以描述一類字符串的模式(Pattern)。如果一個字符串可以用某個正則表達(dá)式來描述,我們就說這個字符和該正則表達(dá)式匹配(Match)。這和DOS中用戶可以使用通配符
“*”代表任意字符類似。在Linux系統(tǒng)上,正則表達(dá)式通常被用來查找文本的模式,以及對文本執(zhí)行“搜索-替換”操作和其它功能。
4.應(yīng)用實例
查詢DNS服務(wù)是日常工作之一,這意味著要維護(hù)覆蓋不同網(wǎng)絡(luò)的大量IP地址。有時IP地址會超過2000個。如果要查看nnn.nnn網(wǎng)絡(luò)地址,但是卻忘了第二部分中的其余部分,只知到有兩個句點,例如nnn nn..。要抽取其中所有nnn.nnn IP地址,使用[0-9 ]\{3
\}\.[0-0\{3\}\。含義是任意數(shù)字出現(xiàn)3次,后跟句點,接著是任意數(shù)字出現(xiàn)3次,后跟句點。
$grep ’[0-9 ]\{3 \}\.[0-0\{3\}\’ ipfile
補(bǔ)充說明,grep家族還包括fgrep和egrep。fgrep是fix grep,允許查找字符串而不是一個模式;egrep是擴(kuò)展grep,支持基本及擴(kuò)展的正則表達(dá)式,但不支持\q模式范圍的應(yīng)用及與之相對應(yīng)的一些更加規(guī)范的模式。
dd
1.作用
dd命令用來復(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ù)以逗號分隔的關(guān)鍵字表示的方式來轉(zhuǎn)換文件。
count=塊數(shù)目:只復(fù)制指定的輸入數(shù)據(jù)。
ibs=字節(jié):每次讀取指定的。
if=文件:讀取內(nèi)容,而非標(biāo)準(zhǔn)輸入的數(shù)據(jù)。
obs=字節(jié):每次寫入指定的。
of=文件:將數(shù)據(jù)寫入,而不在標(biāo)準(zhǔn)輸出顯示。
seek=塊數(shù)目:先略過以obs為單位的指定的輸出數(shù)據(jù)。
skip=塊數(shù)目:先略過以ibs為單位的指定的輸入數(shù)據(jù)。
4.應(yīng)用實例
dd命令常常用來制作Linux啟動盤。先找一個可引導(dǎo)內(nèi)核,令它的根設(shè)備指向正確的根分區(qū),然后使用dd命令將其寫入軟盤:
$ rdev vmlinuz /dev/hda
$dd if=vmlinuz of=/dev/fd0
上面代碼說明,使用rdev命令將可引導(dǎo)內(nèi)核vmlinuz中的根設(shè)備指向/dev/hda,請把“hda”換成自己的根分區(qū),接下來用dd命令將該內(nèi)核寫入軟盤。
find
1.作用
find命令的作用是在目錄中搜索文件,它的使用權(quán)限是所有用戶。
2.格式
find [path][options][expression]
path指定目錄路徑,系統(tǒng)從這里開始沿著目錄樹向下查找文件。它是一個路徑列表,相互用空格分離,如果不寫path,那么默認(rèn)為當(dāng)前目錄。
3.主要參數(shù)
[options]參數(shù):
-depth:使用深度級別的查找過程方式,在某層指定目錄中優(yōu)先查找文件內(nèi)容。
-maxdepth levels:表示至多查找到開始目錄的第level層子目錄。level是一個非負(fù)數(shù),如果level是0的話表示僅在當(dāng)前目錄中查找。
-mindepth levels:表示至少查找到開始目錄的第level層子目錄。
-mount:不在其它文件系統(tǒng)(如Msdos、Vfat等)的目錄和文件中查找。
-version:打印版本。
[expression]是匹配表達(dá)式,是find命令接受的表達(dá)式,find命令的所有操作都是針對表達(dá)式的。它的參數(shù)非常多,這里只介紹一些常用的參數(shù)。
—name:支持統(tǒng)配符*和?。
-atime n:搜索在過去n天讀取過的文件。
-ctime n:搜索在過去n天修改過的文件。
-group grpoupname:搜索所有組為grpoupname的文件。
-user 用戶名:搜索所有文件屬主為用戶名(ID或名稱)的文件。
-size n:搜索文件大小是n個block的文件。
-print:輸出搜索結(jié)果,并且打印。
4.應(yīng)用技巧
find命令查找文件的幾種方法:
(1)根據(jù)文件名查找
例如,我們想要查找一個文件名是lilo.conf的文件,可以使用如下命令:
find / -name lilo.conf
find命令后的“/”表示搜索整個硬盤。
(2)快速查找文件
根據(jù)文件名查找文件會遇到一個實際問題,就是要花費(fèi)相當(dāng)長的一段時間,特別是大型Linux文件系統(tǒng)和大容量硬盤文件放在很深的子目錄中時。如果我們知道了這個文件存放在某個目錄中,那么只要在這個目錄中往下尋找就能節(jié)省很多時間。比如smb.conf文件,從它的文件后綴“.conf”可以判斷這是一個配置文件,那么它應(yīng)該在/etc目錄內(nèi),此時可以使用下面命令:
find /etc -name smb.conf
這樣,使用“快速查找文件”方式可以縮短時間。
(3)根據(jù)部分文件名查找方法
有時我們知道只某個文件包含有abvd這4個字,那么要查找系統(tǒng)中所有包含有這4個字符的文件可以輸入下面命令:
find / -name ’*abvd*’
輸入這個命令以后,Linux系統(tǒng)會將在/目錄中查找所有的包含有abvd這4個字符的文件(其中*是通配符),比如abvdrmyz等符合條件的文件都能顯示出來。
(4) 使用混合查找方式查找文件
find命令可以使用混合查找的方法,例如,我們想在/etc目錄中查找大于500000字節(jié),并且在24小時內(nèi)修改的某個文件,則可以使用-and (與)把兩個查找參數(shù)鏈接起來組合成一個混合的查找方式。
find /etc -size +500000c -and -mtime +1
mv
1.作用
mv命令用來為文件或目錄改名,或者將文件由一個目錄移入另一個目錄中,它的使用權(quán)限是所有用戶。該命令如同DOS命令中的ren和move的組合。
2.格式
mv[options] 源文件或目錄 目標(biāo)文件或目錄
3.[options]主要參數(shù)
-i:交互方式操作。如果mv操作將導(dǎo)致對已存在的目標(biāo)文件的覆蓋,此時系統(tǒng)詢問是否重寫,要求用戶回答“y”或“n”,這樣可以避免誤覆蓋文件。
-f:禁止交互操作。mv操作要覆蓋某個已有的目標(biāo)文件時不給任何指示,指定此參數(shù)后i參數(shù)將不再起作用。
4.應(yīng)用實例
(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:不隱藏任何以“.” 字符開始的項目。
-A, --almost-all:列出除了“ . ”及 “.. ”以外的任何項目。
--author:印出每個文件著作者。
-b, --escape:以八進(jìn)制溢出序列表示不可打印的字符。
--block-size=大小:塊以指定的字節(jié)為單位。
-B, --ignore-backups:不列出任何以 ~ 字符結(jié)束的項目。
-f:不進(jìn)行排序,-aU參數(shù)生效,-lst參數(shù)失效。
-F, --classify:加上文件類型的指示符號 (*/=@| 其中一個)。
-g:like -l, but do not list owner。
-G, --no-group:inhibit display of group information。
-i, --inode:列出每個文件的inode號。
-I, --ignore=樣式:不印出任何符合Shell萬用字符的項目。
-k:即--block-size=1K。
-l:使用較長格式列出信息。
-L, --dereference:當(dāng)顯示符號鏈接的文件信息時,顯示符號鏈接所指示的對象,而并非符號鏈接本身的信息。
-m:所有項目以逗號分隔,并填滿整行行寬。
-n, --numeric-uid-gid:類似-l,但列出UID及GID號。
-N, --literal:列出未經(jīng)處理的項目名稱,例如不特別處理控制字符。
-p, --file-type:加上文件類型的指示符號 (/=@| 其中一個)。
-Q, --quote-name:將項目名稱括上雙引號。
-r, --reverse:依相反次序排列。
-R, --recursive:同時列出所有子目錄層。
-s, --size:以塊大小為序。
4.應(yīng)用舉例
ls
命令是Linux系統(tǒng)使用頻率最多的命令,它的參數(shù)也是Linux命令中最多的。使用ls命令時會有幾種不同的顏色,其中藍(lán)色表示是目錄,綠色表示是可執(zhí)
行文件,紅色表示是壓縮文件,淺藍(lán)色表示是鏈接文件,加粗的黑色表示符號鏈接,灰色表示是其它格式文件。ls最常使用的是ls- l。
文
件類型開頭是由10個字符構(gòu)成的字符串。其中第一個字符表示文件類型,它可以是下述類型之一:-(普通文件)、d(目錄)、l(符號鏈接)、b(塊設(shè)備文件)、c(字符設(shè)備文件)。后面的9個字符表示文件的訪問權(quán)限,分為3組,每組3位。第一組表示文件屬主的權(quán)限,第二組表示同組用戶的權(quán)限,第三組表示其他用戶的權(quán)限。每一組的三個字符分別表示對文件的讀(r)、寫(w)和執(zhí)行權(quán)限(x)。對于目錄,表示進(jìn)入權(quán)限。s表示當(dāng)文件被執(zhí)行時,把該文件的UID 或GID賦予執(zhí)行進(jìn)程的UID(用戶ID)或GID(組ID)。t表示設(shè)置標(biāo)志位(留在內(nèi)存,不被換出)。如果該文件是目錄,那么在該目錄中的文件只能被超級用戶、目錄擁有者或文件屬主刪除。如果它是可執(zhí)行文件,那么在該文件執(zhí)行后,指向其正文段的指針仍留在內(nèi)存。這樣再次執(zhí)行它時,系統(tǒng)就能更快地裝入該文件。接著顯示的是文件大小、生成時間、文件或命令名稱。
Android系統(tǒng)在超級終端下必會的命令大全(四)
diff
1.作用
diff命令用于兩個文件之間的比較,并指出兩者的不同,它的使用權(quán)限是所有用戶。
2.格式
diff [options] 源文件 目標(biāo)文件
3.[options]主要參數(shù)
-a:將所有文件當(dāng)作文本文件來處理。
-b:忽略空格造成的不同。
-B:忽略空行造成的不同。
-c:使用綱要輸出格式。
-H:利用試探法加速對大文件的搜索。
-I:忽略大小寫的變化。
-n --rcs:輸出RCS格式。
cmp
1.作用
cmp(“compare”的縮寫)命令用來簡要指出兩個文件是否存在差異,它的使用權(quán)限是所有用戶。
2.格式
cmp[options] 文件名
3.[options]主要參數(shù)
-l: 將字節(jié)以十進(jìn)制的方式輸出,并方便將兩個文件中不同的以八進(jìn)制的方式輸出。
cat
1.作用
cat(“concatenate”的縮寫)命令用于連接并顯示指定的一個和多個文件的有關(guān)信息,它的使用權(quán)限是所有用戶。
2.格式
cat [options] 文件1 文件2……
3.[options]主要參數(shù)
-n:由第一行開始對所有輸出的行數(shù)編號。
-b:和-n相似,只不過對于空白行不編號。
-s:當(dāng)遇到有連續(xù)兩行以上的空白行時,就代換為一行的空白行。
4.應(yīng)用舉例
(1)cat命令一個最簡單的用處是顯示文本文件的內(nèi)容。例如,我們想在命令行看一下README文件的內(nèi)容,可以使用命令:
$ cat README
(2)有時需要將幾個文件處理成一個文件,并將這種處理的結(jié)果保存到一個單獨(dú)的輸出文件。cat命令在其輸入上接受一個或多個文件,并將它們作為一個單獨(dú)的文件打印到它的輸出。例如,把README和INSTALL的文件內(nèi)容加上行號(空白行不加)之后,將內(nèi)容附加到一個新文本文件File1 中:
$ cat README INSTALL File1
(3)cat 還有一個重要的功能就是可以對行進(jìn)行編號。這種功能對于程序文檔的編制,以及法律和科學(xué)文檔的編制很方便,打印在左邊的行號使得參考文檔的某一部分變得容易,這些在編程、科學(xué)研究、業(yè)務(wù)報告甚至是立法工作中都是非常重要的。對行進(jìn)行編號功能有-b(只能對非空白行進(jìn)行編號)和-n(可以對所有行進(jìn)行編號)兩個參數(shù):
$ cat -b /etc/named.conf
ln
1.作用
ln命令用來在文件之間創(chuàng)建鏈接,它的使用權(quán)限是所有用戶。
2.格式
ln [options] 源文件 [鏈接名]
3.參數(shù)
-f:鏈結(jié)時先將源文件刪除。
-d:允許系統(tǒng)管理者硬鏈結(jié)自己的目錄。
-s:進(jìn)行軟鏈結(jié)(Symbolic Link)。
-b:將在鏈結(jié)時會被覆蓋或刪除的文件進(jìn)行備份。
鏈接有兩種,一種被稱為硬鏈接(Hard Link),另一種被稱為符號鏈接(Symbolic Link)。默認(rèn)情況下,ln命令產(chǎn)生硬鏈接。硬連接指通過索引節(jié)點來進(jìn)行的連接。在Linux的文件系統(tǒng)中,保存在磁盤分區(qū)中的文件不管是什么類型都給它分配一個編號,稱為索引節(jié)點號(InodeIndex)。在Linux中,多個文件名指向同一索引節(jié)點是存在的。一般這種連接就是硬連接。硬連接的作用是允許一個文件擁有多個有效路徑名,這樣用戶就可以建立硬連接到重要文件,以防止“誤刪”的功能。其原因如上所述,因為對應(yīng)該目錄的索引節(jié)點有一個以上的連接。只刪除一個連接并不影響索引節(jié)點本身和其它的連接,只有當(dāng)最后一個連接被刪除后,文件的數(shù)據(jù)塊及目錄的連接才會被釋放。也就是說,文件才會被真正刪除。與硬連接相對應(yīng),Lnux系統(tǒng)中還存在另一種連接,稱為符號連接(Symbilc Link),也叫軟連接。軟鏈接文件有點類似于Windows的快捷方式。它實際上是特殊文件的一種。在符號連接中,文件實際上是一個文本文件,其中包含的有另一文件的位置信息。
--------------------------------------------------------------------------------
作者: ☆-☆ 時間: 2010-6-8 11:55
本帖最后由 ☆-☆ 于 2010-6-8 11:59 編輯
Android系統(tǒng)在超級終端下必會的命令大全(五)
系統(tǒng)管理命令
df
1.作用
df命令用來檢查文件系統(tǒng)的磁盤空間占用情況,使用權(quán)限是所有用戶。
2.格式
df [options]
3.主要參數(shù)
-s:對每個Names參數(shù)只給出占用的數(shù)據(jù)塊總數(shù)。
-a:遞歸地顯示指定目錄中各文件及子目錄中各文件占用的數(shù)據(jù)塊數(shù)。若既不指定-s,也不指定-a,則只顯示Names中的每一個目錄及其中的各子目錄所占的磁盤塊數(shù)。
-k:以1024字節(jié)為單位列出磁盤空間使用情況。
-x:跳過在不同文件系統(tǒng)上的目錄不予統(tǒng)計。
-l:計算所有的文件大小,對硬鏈接文件則計算多次。
-i:顯示inode信息而非塊使用量。
-h:以容易理解的格式印出文件系統(tǒng)大小,例如136KB、254MB、21GB。
-P:使用POSIX輸出格式。
-T:顯示文件系統(tǒng)類型。
4.說明
df 命令被廣泛地用來生成文件系統(tǒng)的使用統(tǒng)計數(shù)據(jù),它能顯示系統(tǒng)中所有的文件系統(tǒng)的信息,包括總?cè)萘俊⒖捎玫目臻e空間、目前的安裝點等。超級權(quán)限用戶使用df 命令時會發(fā)現(xiàn)這樣的情況:某個分區(qū)的容量超過了100%。這是因為Linux系統(tǒng)為超級用戶保留了10%的空間,由其單獨(dú)支配。也就是說,對于超級用戶而言,他所見到的硬盤容量將是110%。這樣的安排對于系統(tǒng)管理而言是有好處的,當(dāng)硬盤被使用的容量接近100%時系統(tǒng)管理員還可以正常工作。
5.應(yīng)用實例
Linux支持的文件系統(tǒng)非常多,包括JFS、ReiserFS、ext、ext2、ext3、ISO9660、XFS、Minx、vfat、MSDOS等。使用df -T命令查看磁盤空間時還可以得到文件系統(tǒng)的信息:
#df -T
文件系統(tǒng) 類型 容量 已用 可用 已用% 掛載點
/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
從上面除了可以看到磁盤空間的容量、使用情況外,分區(qū)的文件系統(tǒng)類型、掛載點等信息也一覽無遺。
top
1.作用
top命令用來顯示執(zhí)行中的程序進(jìn)程,使用權(quán)限是所有用戶。
2.格式
top [-] [d delay] [q] [c] [S] [n]
3.主要參數(shù)
d:指定更新的間隔,以秒計算。
q:沒有任何延遲的更新。如果使用者有超級用戶,則top命令將會以最高的優(yōu)先序執(zhí)行。
c:顯示進(jìn)程完整的路徑與名稱。
S:累積模式,會將己完成或消失的子行程的CPU時間累積起來。
s:安全模式。
i:不顯示任何閑置(Idle)或無用(Zombie)的行程。
n:顯示更新的次數(shù),完成后將會退出top。
4.說明
top命令是Linux系統(tǒng)管理的一個主要命令,通過它可以獲得許多信息。
下面列出了詳細(xì)解釋。
PID(Process ID):進(jìn)程標(biāo)示號。
USER:進(jìn)程所有者的用戶名。
PR:進(jìn)程的優(yōu)先級別。
NI:進(jìn)程的優(yōu)先級別數(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)程啟動后占用的總的CPU時間。
Command:進(jìn)程啟動的啟動命令名稱,如果這一行顯示不下,進(jìn)程會有一個完整的命令行。
top命令使用過程中,還可以使用一些交互的命令來完成其它參數(shù)的功能。這些命令是通過快捷鍵啟動的。
:立刻刷新。
P:根據(jù)CPU使用大小進(jìn)行排序。
T:根據(jù)時間、累計時間排序。
q:退出top命令。
m:切換顯示內(nèi)存信息。
t:切換顯示進(jìn)程和CPU狀態(tài)信息。
c:切換顯示命令名稱和完整命令行。
M:根據(jù)使用內(nèi)存大小進(jìn)行排序。
W:將當(dāng)前設(shè)置寫入~/.toprc文件中。這是寫top配置文件的推薦方法。
可以看到,top命令是一個功能十分強(qiáng)大的監(jiān)控系統(tǒng)的工具,對于系統(tǒng)管理員而言尤其重要。但是,它的缺點是會消耗很多系統(tǒng)資源。
free
1.作用
free命令用來顯示內(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ù)來顯示一次內(nèi)存使用情況。
-t:顯示內(nèi)存總和列。
-o:不顯示緩沖區(qū)調(diào)節(jié)列。
4.應(yīng)用實例
free命令是用來查看內(nèi)存使用情況的主要命令。和top命令相比,它的優(yōu)點是使用簡單,并且只占用很少的系統(tǒng)資源。通過-S參數(shù)可以使用free命令不間斷地監(jiān)視有多少內(nèi)存在使用,這樣可以把它當(dāng)作一個方便實時監(jiān)控器。
#free -b -s5
使用這個命令后終端會連續(xù)不斷地報告內(nèi)存使用情況(以字節(jié)為單位),每5秒更新一次。
chown
1.作用
更改一個或多個文件或目錄的屬主和屬組。使用權(quán)限是超級用戶。
2.格式
chown [選項] 用戶或組 文件
3.主要參數(shù)
--dereference:受影響的是符號鏈接所指示的對象,而非符號鏈接本身。
-h, --no-dereference:會影響符號鏈接本身,而非符號鏈接所指示的目的地(當(dāng)系統(tǒng)支持更改符號鏈接的所有者,此選項才有效)。
--from=目前所有者:目前組只當(dāng)每個文件的所有者和組符合選項所指定的,才會更改所有者和組。其中一個可以省略,這已省略的屬性就不需要符合原有的屬性。
-f, --silent, --quiet:去除大部分的錯誤信息。
-R, --recursive:遞歸處理所有的文件及子目錄。
-v, --verbose:處理任何文件都會顯示信息。
4.說明
chown 將指定文件的擁有者改為指定的用戶或組,用戶可以是用戶名或用戶ID;組可以是組名或組ID;文件是以空格分開的要改變權(quán)限的文件列表,支持通配符。系統(tǒng)管理員經(jīng)常使用chown命令,在將文件拷貝到另一個用戶的目錄下以后,讓用戶擁有使用該文件的權(quán)限。
5.應(yīng)用實例
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)限超級用戶。
2.格式
chattr [-RV] [-+=AacDdijsSu] [-v version] 文件或目錄
3.主要參數(shù)
-R:遞歸處理所有的文件及子目錄。
-V:詳細(xì)顯示修改內(nèi)容,并打印輸出。
-:失效屬性。
+:激活屬性。
= :指定屬性。
A:Atime,告訴系統(tǒng)不要修改對這個文件的最后訪問時間。
S:Sync,一旦應(yīng)用程序?qū)@個文件執(zhí)行了寫操作,使系統(tǒng)立刻把修改的結(jié)果寫到磁盤。
a:Append Only,系統(tǒng)只允許在這個文件之后追加數(shù)據(jù),不允許任何進(jìn)程覆蓋或截斷這個文件。如果目錄具有這個屬性,系統(tǒng)將只允許在這個目錄下建立和修改文件,而不允許刪除任何文件。
i:Immutable,系統(tǒng)不允許對這個文件進(jìn)行任何的修改。如果目錄具有這個屬性,那么任何的進(jìn)程只能修改目錄之下的文件,不允許建立和刪除文件。
D:檢查壓縮文件中的錯誤。
d:No dump,在進(jìn)行文件系統(tǒng)備份時,dump程序?qū)⒑雎赃@個文件。
C:Compress,系統(tǒng)以透明的方式壓縮這個文件。從這個文件讀取時,返回的是解壓之后的數(shù)據(jù);而向這個文件中寫入數(shù)據(jù)時,數(shù)據(jù)首先被壓縮之后才寫入磁盤。
s:Secure Delete,讓系統(tǒng)在刪除這個文件時,使用0填充文件所在的區(qū)域。
u:Undelete,當(dāng)一個應(yīng)用程序請求刪除這個文件,系統(tǒng)會保留其數(shù)據(jù)塊以便以后能夠恢復(fù)刪除這個文件。
4.說明
chattr
命令的作用很大,其中一些功能是由Linux內(nèi)核版本來支持的,如果Linux內(nèi)核版本低于2.2,那么許多功能不能實現(xiàn)。同樣-D檢查壓縮文件中的錯誤
的功能,需要2.5.19以上內(nèi)核才能支持。另外,通過chattr命令修改屬性能夠提高系統(tǒng)的安全性,但是它并不適合所有的目錄。chattr命令不能
保護(hù)/、/dev、/tmp、/var目錄。
5.應(yīng)用實例
1.恢復(fù)/root目錄,即子目錄的所有文件
# chattr -R +u/root
2.用chattr命令防止系統(tǒng)中某個關(guān)鍵文件被修改
在Linux下,有些配置文件(passwd ,fatab)是不允許任何人修改的,為了防止被誤刪除或修改,可以設(shè)定該文件的“不可修改位(immutable)”,命令如下:
# chattr +i /etc/fstab
ps
1.作用
ps顯示瞬間進(jìn)程 (process) 的動態(tài),使用權(quán)限是所有使用者。
2.格式
ps [options] [--help]
3.主要參數(shù)
ps的參數(shù)非常多, 此出僅列出幾個常用的參數(shù)。
-A:列出所有的進(jìn)程。
-l:顯示長列表。
-m:顯示內(nèi)存信息。
-w:顯示加寬可以顯示較多的信息。
-e:顯示所有進(jìn)程。
a:顯示終端上的所有進(jìn)程,包括其它用戶的進(jìn)程。
-au:顯示較詳細(xì)的信息。
-aux:顯示所有包含其它使用者的進(jìn)程。
4.說明
要
對進(jìn)程進(jìn)行監(jiān)測和控制,首先要了解當(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)程有沒有僵尸、哪些進(jìn)程占用了過多的資源等。圖2給出了ps-aux命令詳解。大部分信息都可以通過執(zhí)行該命
令得到。最常用的三個參數(shù)是u、a、x。下面就結(jié)合這三個參數(shù)詳細(xì)說明ps命令的作用:ps aux
圖2 ps-aux命令詳解
圖2第2行代碼中,USER表示進(jìn)程擁有者;PID表示進(jìn)程標(biāo)示符;%CPU表示占用的CPU使用率;%MEM占用的物理內(nèi)存使用率;VSZ表示占用的虛擬內(nèi)存大小;RSS為進(jìn)程占用的物理內(nèi)存值;TTY為終端的次要裝置號碼。
STAT
表示進(jìn)程的狀態(tài),其中D為不可中斷的靜止(I/O動作);R正在執(zhí)行中;S靜止?fàn)顟B(tài);T暫停執(zhí)行;Z不存在,但暫時無法消除;W沒有足夠的內(nèi)存分頁可分
配;高優(yōu)先序的進(jìn)程;N低優(yōu)先序的進(jìn)程;L有內(nèi)存分頁分配并鎖在內(nèi)存體內(nèi) (實時系統(tǒng)或
I/O)。START為進(jìn)程開始時間。TIME為執(zhí)行的時間。COMMAND是所執(zhí)行的指令。
4.應(yīng)用實例
在進(jìn)行系統(tǒng)維護(hù)時,經(jīng)常會出現(xiàn)內(nèi)存使用量驚人,而又不知道是哪一個進(jìn)程占用了大量進(jìn)程的情況。除了可以使用top命令查看內(nèi)存使用情況之外,還可以使用下面的命令:
ps aux | sort +5n
--------------------------------------------------------------------------------
作者: ☆-☆ 時間: 2010-6-8 11:58
Android系統(tǒng)在超級終端下必會的命令大全(十)
六、其他命令
tar
1.作用
tar命令是Unix/Linux系統(tǒng)中備份文件的可靠方法,幾乎可以工作于任何環(huán)境中,它的使用權(quán)限是所有用戶。
2.格式
tar [主選項+輔選項] 文件或目錄
3.主要參數(shù)
使用該命令時,主選項是必須要有的,它告訴tar要做什么事情,輔選項是輔助使用的,可以選用。
主選項:
-c 創(chuàng)建新的檔案文件。如果用戶想備份一個目錄或是一些文件,就要選擇這個選項。
-r 把要存檔的文件追加到檔案文件的未尾。例如用戶已經(jīng)做好備份文件,又發(fā)現(xiàn)還有一個目錄或是一些文件忘記備份了,這時可以使用該選項,將忘記的目錄或文件追加到備份文件中。
-t 列出檔案文件的內(nèi)容,查看已經(jīng)備份了哪些文件。
-u 更新文件。就是說,用新增的文件取代原備份文件,如果在備份文件中找不到要更新的文件,則把它追加到備份文件的最后。
-x 從檔案文件中釋放文件。
輔助選項:
-b 該選項是為磁帶機(jī)設(shè)定的,其后跟一數(shù)字,用來說明區(qū)塊的大小,系統(tǒng)預(yù)設(shè)值為20(20×512 bytes)。
-f 使用檔案文件或設(shè)備,這個選項通常是必選的。
-k 保存已經(jīng)存在的文件。例如把某個文件還原,在還原的過程中遇到相同的文件,不會進(jìn)行覆蓋。
-m 在還原文件時,把所有文件的修改時間設(shè)定為現(xiàn)在。
-M 創(chuàng)建多卷的檔案文件,以便在幾個磁盤中存放。
-v 詳細(xì)報告tar處理的文件信息。如無此選項,tar不報告文件信息。
-w 每一步都要求確認(rèn)。
-z 用gzip來壓縮/解壓縮文件,加上該選項后可以將檔案文件進(jìn)行壓縮,但還原時也一定要使用該選項進(jìn)行解壓縮。
4.應(yīng)用說明
tar 是Tape Archive(磁帶歸檔)的縮寫,最初設(shè)計用于將文件打包到磁帶上。如果下載過Linux的源代碼,或許已經(jīng)碰到過tar文件
請注意,不要忘了Linux是區(qū)分大小寫的。例如,tar命令應(yīng)該總是以小寫的形式執(zhí)行。命令行開關(guān)可以是大寫、小寫或大小寫的混合。例如,-t和-T執(zhí)行不同的功能。文件或目錄名稱可以混合使用大小寫,而且就像命令和命令行開關(guān)一樣是區(qū)分大小寫的。
5.應(yīng)用實例
tar是一個命令行的工具,沒有圖形界面。使用Konsole打開一個終端窗口,接下來是一個簡單的備份命令(在/temp目錄中創(chuàng)建一個back.tar的文件,/usr目錄中所有內(nèi)容都包含在其中。):
$tar cvf - /usr > /temp/back.tar
另
外,tar命令支持前面第三講中講過的crontab命令,可以用crontab工具設(shè)置成基于時間的有規(guī)律地運(yùn)行。例如,每晚6點把/usr目錄備份到
hda—第一個IDE接口的主驅(qū)動器 (總是位于第一個硬盤)中,只要將下面語句添加到root的crontab中即可:
$00 06 * * * tar cvf /dev/hda1/usrfiles.tar - /usr
一般情況下,以下這些目錄是需要備份的:
◆/etc 包含所有核心配置文件,其中包括網(wǎng)絡(luò)配置、系統(tǒng)名稱、防火墻規(guī)則、用戶、組,以及其它全局系統(tǒng)項。
◆ /var 包含系統(tǒng)守護(hù)進(jìn)程(服務(wù))所使用的信息,包括DNS配置、DHCP租期、郵件緩沖文件、HTTP服務(wù)器文件、dB2實例配置等。
◆/home 包含所有默認(rèn)用戶的主目錄,包括個人設(shè)置、已下載的文件和用戶不希望失去的其它信息。
◆/root 根(root)用戶的主目錄。
◆/opt 是安裝許多非系統(tǒng)文件的地方。IBM軟件就安裝在這里。OpenOffice、JDK和其它軟件在默認(rèn)情況下也安裝在這里。
有些目錄是可以不備份的:
◆ /proc 應(yīng)該永遠(yuǎn)不要備份這個目錄。它不是一個真實的文件系統(tǒng),而是運(yùn)行內(nèi)核和環(huán)境的虛擬化視圖,包括諸如/proc/kcore這樣的文件,這個文件是整個運(yùn)行內(nèi)存的虛擬視圖。備份這些文件只是在浪費(fèi)資源。
◆/dev 包含硬件設(shè)備的文件表示。如果計劃還原到一個空白的系統(tǒng),就可以備份/dev。然而,如果計劃還原到一個已安裝的Linux 系統(tǒng),那么備份/dev是沒有必要的。
unzip
1.作用
unzip
命令位于/usr/bin目錄中,它們和MS DOS下的pkzip、pkunzip及MS
Windows中的Winzip軟件功能一樣,將文件壓縮成.zip文件,以節(jié)省硬盤空間,當(dāng)需要的時候再將壓縮文件用unzip命令解開。該命令使用權(quán)
限是所有用戶。
2.格式
unzip [-cflptuvz][-agCjLMnoqsVX][-P ][.zip文件][文件][-d ][-x ]
3.主要參數(shù)
-c:將解壓縮的結(jié)果顯示到屏幕上,并對字符做適當(dāng)?shù)霓D(zhuǎn)換。
-f:更新現(xiàn)有的文件。
-l:顯示壓縮文件內(nèi)所包含的文件。
-p:與-c參數(shù)類似,會將解壓縮的結(jié)果顯示到屏幕上,但不會執(zhí)行任何的轉(zhuǎn)換。
-t:檢查壓縮文件是否正確。
-u:與-f參數(shù)類似,但是除了更新現(xiàn)有的文件外,也會將壓縮文件中的其它文件解壓縮到目錄中。
-v:執(zhí)行是時顯示詳細(xì)的信息。
-z:僅顯示壓縮文件的備注文字。
-a:對文本文件進(jìn)行必要的字符轉(zhuǎn)換。
-b:不要對文本文件進(jìn)行字符轉(zhuǎn)換。
-C:壓縮文件中的文件名稱區(qū)分大小寫。
-j:不處理壓縮文件中原有的目錄路徑。
-L:將壓縮文件中的全部文件名改為小寫。
-M:將輸出結(jié)果送到more程序處理。
-n:解壓縮時不要覆蓋原有的文件。
-o:不必先詢問用戶,unzip執(zhí)行后覆蓋原有文件。
-P:使用zip的密碼選項。
-q:執(zhí)行時不顯示任何信息。
-s:將文件名中的空白字符轉(zhuǎn)換為底線字符。
-V:保留VMS的文件版本信息。
-X:解壓縮時同時回存文件原來的UID/GID。
[.zip文件]:指定.zip壓縮文件。
[文件]:指定要處理.zip壓縮文件中的哪些文件。
-d:指定文件解壓縮后所要存儲的目錄。
-x:指定不要處理.zip壓縮文件中的哪些文件。
-Z unzip:-Z等于執(zhí)行zipinfo指令。在Linux中,還提供了一個叫zipinfo的工具,能夠察看zip壓縮文件的詳細(xì)信息。
gunzip
1.作用
gunzip命令作用是解壓文件,使用權(quán)限是所有用戶。
2.格式
gunzip [-acfhlLnNqrtvV][-s ][文件...]
或者
gunzip [-acfhlLnNqrtvV][-s ][目錄]
3.主要參數(shù)
-a或--ascii:使用ASCII文字模式。
-c或--stdout或--to-stdout:把解壓后的文件輸出到標(biāo)準(zhǔn)輸出設(shè)備。
-f或-force:強(qiáng)行解開壓縮文件,不理會文件名稱或硬連接是否存在,以及該文件是否為符號連接。
-h或--help:在線幫助。
-l或--list:列出壓縮文件的相關(guān)信息。
-L或--license:顯示版本與版權(quán)信息。
-n或--no-name:解壓縮時,若壓縮文件內(nèi)含有原來的文件名稱及時間戳記,則將其忽略不予處理。
-N或--name:解壓縮時,若壓縮文件內(nèi)含有原來的文件名稱及時間戳記,則將其回存到解開的文件上。
-q或--quiet:不顯示警告信息。
-r或--recursive:遞歸處理,將指定目錄下的所有文件及子目錄一并處理。
-S或--suffix:更改壓縮字尾字符串。
-t或--test:測試壓縮文件是否正確無誤。
-v或--verbose:顯示指令執(zhí)行過程。
-V或--version:顯示版本信息。
4.說明
gunzip是個使用廣泛的解壓縮程序,它用于解開被gzip壓縮過的文件,這些壓縮文件預(yù)設(shè)最后的擴(kuò)展名為“.gz”。事實上,gunzip就是gzip的硬連接,因此不論是壓縮或解壓縮,都可通過gzip指令單獨(dú)完成。gunzip最新版本是1.3.3 。
- 12:39
- 評論 / 瀏覽 (0 / 23)
- 分類:移動開發(fā)
java runtime.exec()相關(guān)
java那就首先說點Runtime類吧,他是一個與JVM運(yùn)行時環(huán)境有關(guān)的類,這個類是Singleton的。我說幾個自己覺得重要的地方。
1、Runtime.getRuntime()可以取得當(dāng)前JVM的運(yùn)行時環(huán)境,這也是在Java中唯一一個得到運(yùn)行時環(huán)境的方法。
2、Runtime上其他大部分的方法都是實例方法,也就是說每次進(jìn)行運(yùn)行時調(diào)用時都要用到getRuntime方法。
3、 Runtime中的exit方法是退出當(dāng)前JVM的方法,估計也是唯一的一個吧,因為我看到System類中的exit實際上也是通過調(diào)用 Runtime.exit()來退出JVM的,這里說明一下Java對Runtime返回值的一般規(guī)則(后邊也提到了),0代表正常退出,非0代表異常中止,這只是Java的規(guī)則,在各個操作系統(tǒng)中總會發(fā)生一些小的混淆。
4、Runtime.addShutdownHook()方法可以注冊一個hook在JVM執(zhí)行shutdown的過程中,方法的參數(shù)只要是一個初始化過但是沒有執(zhí)行的Thread實例就可以。(注意,Java中的Thread都是執(zhí)行過了就不值錢的哦)
5、說到addShutdownHook這個方法就要說一下JVM運(yùn)行環(huán)境是在什么情況下shutdown或者abort的。文檔上是這樣寫的,當(dāng)最后一個非精靈進(jìn)程退出或者收到了一個用戶中斷信號、用戶登出、系統(tǒng)shutdown、Runtime的exit方法被調(diào)用時JVM會啟動shutdown的過程,在這個過程開始后,他會并行啟動所有登記的shutdown hook(注意是并行啟動,這就需要線程安全和防止死鎖)。當(dāng)shutdown過程啟動后,只有通過調(diào)用halt方法才能中止shutdown的過程并退出JVM。
那什么時候JVM會abort退出那?首先說明一下,abort退出時JVM就是停止運(yùn)行但并不一定進(jìn)行shutdown。這只有JVM在遇到SIGKILL信號或者windows中止進(jìn)程的信號、本地方法發(fā)生類似于訪問非法地址一類的內(nèi)部錯誤時會出現(xiàn)。這種情況下并不能保證shutdown hook是否被執(zhí)行。
現(xiàn)在開始看這篇文章,呵呵。
首先講的是Runtime.exec()方法的所有重載。這里要注意的有一點,就是public Process exec(String [] cmdArray, String [] envp);這個方法中cmdArray是一個執(zhí)行的命令和參數(shù)的字符串?dāng)?shù)組,數(shù)組的第一個元素是要執(zhí)行的命令往后依次都是命令的參數(shù),envp我個人感覺應(yīng)該和C中的execve中的環(huán)境變量是一樣的,envp中使用的是name=value的方式。
<!--[if !supportLists]-->1、 <!--[endif]-->一個很糟糕的調(diào)用程序,代碼如下,這個程序用exec調(diào)用了一個外部命令之后馬上使用exitValue就對其返回值進(jìn)行檢查,讓我們看看會出現(xià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)
這里看原文就可以了解,這里主要的問題就是錯誤的調(diào)用了exitValue來取得外部命令的返回值(呵呵,這個錯誤我也曾經(jīng)犯過),因為exitValue 這個方法是不阻塞的,程序在調(diào)用這個方法時外部命令并沒有返回所以造成了異常的出現(xiàn),這里是由另外的方法來等待外部命令執(zhí)行完畢的,就是waitFor方法,這個方法會一直阻塞直到外部命令執(zhí)行結(jié)束,然后返回外部命令執(zhí)行的結(jié)果,作者在這里一頓批評設(shè)計者的思路有問題,呵呵,反正我是無所謂阿,能用就可以拉。但是作者在這里有一個說明,就是exitValue也是有好多用途的。因為當(dāng)你在一個Process上調(diào)用waitFor方法時,當(dāng)前線程是阻塞的,如果外部命令無法執(zhí)行結(jié)束,那么你的線程就會一直阻塞下去,這種意外會影響我們程序的執(zhí)行。所以在我們不能判斷外部命令什么時候執(zhí)行完畢而我們的程序還需要繼續(xù)執(zhí)行的情況下,我們就應(yīng)該循環(huán)的使用exitValue來取得外部命令的返回狀態(tài),并在外部命令返回時作出相應(yīng)的處理。
2、對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();
}
}
}
不幸的是,這個程序也無法執(zhí)行完成,它沒有輸出但卻一直懸在那里,這是為什么那?
JDK文檔中對此有如此的解釋:因為本地的系統(tǒng)對標(biāo)準(zhǔn)輸入和輸出所提供的緩沖池有效,所以錯誤的對標(biāo)準(zhǔn)輸出快速的寫入和從標(biāo)準(zhǔn)輸入快速的讀入都有可能造成子進(jìn)程的鎖,甚至死鎖。
文檔引述完了,作者又開始批評了,他說JDK僅僅說明為什么問題會發(fā)生,卻并沒有說明這個問題怎么解決,這的確是個問題哈。緊接著作者說出自己的做法,就是在執(zhí)行完外部命令后我們要控制好Process的所有輸入和輸出(視情況而定),在這個例子里邊因為調(diào)用的是Javac,而他在沒有參數(shù)的情況下會將提示信息輸出到標(biāo)準(zhǔn)出錯,所以在下面的程序中我們要對此進(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
哎,不管怎么說還是出來了結(jié)果,作者作了一下總結(jié),就是說,為了處理好外部命令大量輸出的情況,你要確保你的程序處理好外部命令所需要的輸入或者輸出。
下一個題目,當(dāng)我們調(diào)用一個我們認(rèn)為是可執(zhí)行程序的時候容易發(fā)生的錯誤(今天晚上我剛剛犯這個錯誤,沒事做這個練習(xí)時候發(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)
說實在的,這個錯誤還真是讓我摸不著頭腦,我覺得在windows中返回2應(yīng)該是沒有找到這個文件的緣故,可能windows 2000中只有cmd命令,dir命令不是當(dāng)前環(huán)境變量能夠解釋的吧。我也不知道了,慢慢往下看吧。
嘿,果然和作者想的一樣,就是因為dir命令是由windows中的解釋器解釋的,直接執(zhí)行dir時無法找到dir.exe這個命令,所以會出現(xiàn)文件未找到這個2的錯誤。如果我們要執(zhí)行這樣的命令,就要先根據(jù)操作系統(tǒng)的不同執(zhí)行不同的解釋程序command.com 或者cmd.exe。
作者對上邊的程序進(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
這里作者教了一個windows中很有用的方法,呵呵,至少我是不知道的,就是cmd.exe /C +一個windows中注冊了后綴的文檔名,windows會自動地調(diào)用相關(guān)的程序來打開這個文檔,我試了一下,的確很好用,但是好像文件路徑中有空格的話就有點問題,我加上引號也無法解決。
這里作者強(qiáng)調(diào)了一下,不要假設(shè)你執(zhí)行的程序是可執(zhí)行的程序,要清楚自己的程序是單獨(dú)可執(zhí)行的還是被解釋的,本章的結(jié)束作者會介紹一個命令行工具來幫助我們分析。
這里還有一點,就是得到process的輸出的方式是getInputStream,這是因為我們要從Java 程序的角度來看,外部程序的輸出對于Java來說就是輸入,反之亦然。
最后的一個漏洞的地方就是錯誤的認(rèn)為exec方法會接受所有你在命令行或者Shell中輸入并接受的字符串。這些錯誤主要出現(xiàn)在命令作為參數(shù)的情況下,程序員錯誤的將所有命令行中可以輸入的參數(shù)命令加入到exec中(這段翻譯的不好,湊合看吧)。下面的例子中就是一個程序員想重定向一個命令的輸出。
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這個輸入重訂向到一個文本文件中,但是這個文件并沒有生成,jecho僅僅是將命令行中的參數(shù)輸出到標(biāo)準(zhǔn)輸出中,用戶覺得可以像dos中重定向一樣將輸出重定向到一個文件中,但這并不能實現(xiàn),用戶錯誤的將exec認(rèn)為是一個shell解釋器,但它并不是,如果你想將一個程序的輸出重定向到其他的程序中,你必須用程序來實現(xiàn)他。可用java.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
這里就不多說了,看看就明白,緊接著作者給出了一個監(jiān)測命令的小程序
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();
}
}
}
對這個程序進(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中是說這不是一個win32程序,這說明路徑中找不到這個網(wǎng)頁的關(guān)聯(lián)程序,下面作者決定用一個絕對路徑來試一下。
E:classescomjavaworldjpitfallsarticle2>java TestExec
"e:program filesnetscapeprogramnetscape.exe e:javadocsindex.html"
ExitValue: 0
好用了,這個我也試了一下,用的是IE。
最后,作者總結(jié)了幾條規(guī)則,防止我們在進(jìn)行Runtime.exec()調(diào)用時出現(xiàn)錯誤。
<!--[if !supportLists]-->1、 <!--[endif]-->在一個外部進(jìn)程執(zhí)行完之前你不能得到他的退出狀態(tài)
<!--[if !supportLists]-->2、 <!--[endif]-->在你的外部程序開始執(zhí)行的時候你必須馬上控制輸入、輸出、出錯這些流。
<!--[if !supportLists]-->3、 <!--[endif]-->你必須用Runtime.exec()去執(zhí)行程序
<!--[if !supportLists]-->4、 <!--[endif]-->你不能象命令行一樣使用Runtime.exec()。
- 12:35
- 評論 / 瀏覽 (0 / 11)
- 分類:編程語言
FileInputStream/FileOutputStream的應(yīng)用
javafileoutputstreamfileinputstream 這是一對繼承于InputStream和OutputStream的類,用于本地文件讀寫(二進(jìn)制格式讀寫并且是順序讀寫,讀和寫要分別創(chuàng)建出不同的文件流對象);本地文件讀寫編程的基本過程為:
① 生成文件流對象(對文件讀操作時應(yīng)該為FileInputStream類,而文件寫應(yīng)該為FileOutputStream類);
② 調(diào)用FileInputStream或FileOutputStream類中的功能函數(shù)如read()、write(int b)等)讀寫文件內(nèi)容;
③ 關(guān)閉文件(close())。
實例:流文件讀寫
流文件的單元是字節(jié),所以它不但可以讀寫文本文件,也可以讀寫圖片、聲音、影像文件,這種特點非常有用,因為我們可以把這種文件變成流,然后在網(wǎng)絡(luò)上傳輸。
問題是有了通用的流文件以后,為什么還要專門的字符流呢?這是因為文本可以用不同的方式存儲,可以是普通的文本(UTF-8編碼方式),ASCII文本和Unicode文本,字符流對象可以進(jìn)行必要的轉(zhuǎn)換,從而讀出正確的文本。
有人認(rèn)為流文件不能讀寫文本文件,這其實是個誤會,因為文本文件本質(zhì)上也是由字節(jié)組成的,當(dāng)然是流文件的一種。作為讀寫文件的全體,這是沒問題的,但是,如果要處理每次讀入的內(nèi)容,就最好使用字符流。
所以在文本文件處理時,使用字符流是個最常用的方法。
樣例:
import java.io.*;
public class FileStreamDemo {
public static void main(String[] args) throws IOException {
//創(chuàng)建兩個文件,face.gif是已經(jīng)存在文件,newFace.gif是新創(chuàng)建的文件
File inFile = new File("face.gif");
File outFile = new File("newFace.gif");
//創(chuàng)建流文件讀入與寫出類
FileInputStream inStream = new FileInputStream(inFile);
FileOutputStream outStream = new FileOutputStream(outFile);
//通過available方法取得流的最大字符數(shù)
byte[] inOutb = new byte[inStream.available()];
inStream.read(inOutb); //讀入流,保存在byte數(shù)組
outStream.write(inOutb); //寫出流,保存在文件newFace.gif中
inStream.close();
outStream.close();
}
}
實例:讀寫任意大文件應(yīng)用
因為byte數(shù)組最大存儲值不超過64M,所以當(dāng)一個文件大于60M 的時候,需要分開幾個流操作。我們把上面的程序作一個修改,就可以寫入任意大小的文件。這個程序應(yīng)用了FileInputStream類的方法如下:
read(byte[] b,int off,int len)
把特定位置的流內(nèi)容讀入數(shù)組,已經(jīng)讀入byte[]數(shù)組的內(nèi)容,會在流文件中刪除。
程序運(yùn)行的結(jié)果會產(chǎn)生一個新文件。
樣例:
import java.io.*;
public class FileStreamDemo2 {
public static void main(String[] args) throws IOException {
//創(chuàng)建兩個文件
File inFile = new File("tcty36.rm");
File outFile = new File("newtcty36.rm");
//最大的流為60Mb,當(dāng)文件的容量大于60Mb的時候便分開流
final int MAX_BYTE = 60000000;
long streamTotal = 0; //接受流的容量
int streamNum = 0; //流需要分開的數(shù)量
int leave = 0; //文件剩下的字符數(shù)
byte[] inOutb; //byte數(shù)組接受文件的數(shù)據(jù)
//創(chuàng)建流文件讀入與寫出類
FileInputStream inStream = new FileInputStream(inFile);
FileOutputStream outStream = new FileOutputStream(outFile);
//通過available方法取得流的最大字符數(shù)
streamTotal = inStream.available();
//取得流文件需要分開的數(shù)量
streamNum = (int)Math.floor(streamTotal/MAX_BYTE);
//分開文件之后,剩余的數(shù)量
leave = (int)streamTotal % MAX_BYTE;
//文件的容量大于60Mb時進(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); //寫出流
outStream.flush(); //更新寫出的結(jié)果
}
}
//寫出剩下的流數(shù)據(jù)
inOutb = new byte[leave];
inStream.read(inOutb, 0, leave);
outStream.write(inOutb);
outStream.flush();
inStream.close();
outStream.close();
}
}
六、管道PipedInputStream/PipedOutputStream類:
當(dāng)需要在兩個線程中讀寫數(shù)據(jù)的時候,由于線程的并發(fā)執(zhí)行,讀寫的同步問題可能會發(fā)生困難,這時候可以使用管道,管道事實上是一個隊列。
管道是由系統(tǒng)維護(hù)的一個緩沖區(qū),當(dāng)然程序員也可以自己直接指定該緩沖區(qū)的大小(只需要設(shè)置管道流類中的PIPE_SIZE屬性的值)。當(dāng)生產(chǎn)者生產(chǎn)出數(shù)據(jù)后,只需要將數(shù)據(jù)寫入管道中,消費(fèi)者只需要從管道中讀取所需要的數(shù)據(jù)。利用管道的這種機(jī)制,可以將一個線程的輸出結(jié)果直接連接到另一個線程的輸入端口,實現(xiàn)兩者之間的數(shù)據(jù)直接傳送。
線程1
線程2
臨時文件
管道
1.管道的連接:
方法之一是通過構(gòu)造函數(shù)直接將某一個程序的輸出作為另一個程序的輸入,在定義對象時指明目標(biāo)管道對象
PipedInputStream pInput=new PipedInputStream();
PipedOutputStream pOutput= new PipedOutputStream(pInput);
方法之二是利用雙方類中的任一個成員函數(shù) connect()相連接
PipedInputStream pInput=new PipedInputStream();
PipedOutputStream pOutput= new PipedOutputStream();
pinput.connect(pOutput);
2.管道的輸入與輸出:
輸出管道對象調(diào)用write()成員函數(shù)輸出數(shù)據(jù)(即向管道的輸入端發(fā)送數(shù)據(jù));而輸入管道對象調(diào)用read()成員函數(shù)可以讀起數(shù)據(jù)(即從輸出管道中獲得數(shù)據(jù))。這主要是借助系統(tǒng)所提供的緩沖機(jī)制來實現(xiàn)的。
實例:Java的管道的輸入與輸出
import java.io.*;
public class PipedIO //程序運(yùn)行后將sendFile文件的內(nèi)容拷貝到receiverFile文件中
{
public static void main(String args[])
{
try
{
//構(gòu)造讀寫的管道流對象
PipedInputStream pis=new PipedInputStream();
PipedOutputStream pos=new PipedOutputStream();
//實現(xiàn)關(guān)聯(lián)
pos.connect(pis);
//構(gòu)造兩個線程,并且啟動。
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)
{
//寫入管道始端
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
{
//寫文件流對象
FileOutputStream fs=new FileOutputStream(file);
int data;
//從管道末端讀
while((data=pis.read())!=-1)
{
//寫入本地文件
fs.write(data);
}
pis.close();
}
catch(IOException e)
{
System.out.println("Receiver Error" +e);
}
}
}
七、隨機(jī)文件讀寫:RandomAccessFile類
它直接繼承于Object類而非InputStream/OutputStream類,從而可以實現(xiàn)讀寫文件中任何位置中的數(shù)據(jù)(只需要改變文件的讀寫位置的指針)。
編程步驟:
① 生成流對象并且指明讀寫類型;
② 移動讀寫位置;
③ 讀寫文件內(nèi)容;
④ 關(guān)閉文件。
另外由于RandomAccessFile類實現(xiàn)了DataOutput與DataInput接口,因而利用它可以讀寫Java中的不同類型的基本類型數(shù)據(jù)(比如采用readLong()方法讀取長整數(shù),而利用readInt()方法可以讀出整數(shù)值等)。
程序?qū)嵗?#xff1a;
利用隨機(jī)數(shù)據(jù)流RandomAccessFile類來實現(xiàn)記錄用戶在鍵盤的輸入,每執(zhí)行一次,將用戶的鍵盤輸入存儲在指定的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);
}
//讀寫方式可以為"r" or "rw"
RandomAccessFile myFileStream=new RandomAccessFile("c:\\UserInput.txt","rw");
myFileStream.seek(myFileStream.length()) ;
myFileStream.writeBytes(buf.toString());
//將用戶從鍵盤輸入的內(nèi)容添加到文件的尾部
myFileStream.close();
}
catch(IOException e)
{
}
}
}
八、DataInput/DataOutput接口:
實現(xiàn)與機(jī)器無關(guān)的各種數(shù)據(jù)格式讀寫(如readChar() 、readInt()、readLong()、readFloat(),而readLine()將返回一個String)。其中 RandomAccessFile類實現(xiàn)了該接口,具有比FileInputStream或FileOutputStream類更靈活的數(shù)據(jù)讀寫方式。
- 12:27
- 評論 / 瀏覽 (0 / 17)
- 分類:編程語言
Linux C 創(chuàng)建目錄函數(shù)mkdir相關(guān)
linuxc I.Linux C 創(chuàng)建目錄函數(shù)mkdir的mode設(shè)置問題函數(shù)原型:
#include <sys/stat.h>
int mkdir(const char *path, mode_t mode);
參數(shù):
path是目錄名
mode是目錄權(quán)限
返回值:
返回0 表示成功, 返回 -1表示錯誤,并且會設(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)建了一個newdir目錄,權(quán)限通過ls -al 查看為
drwxr-xr-x
跟用linux命令mkdir創(chuàng)建的目錄權(quán)限位一致。
II. linux下C語言創(chuàng)建多級目錄
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)建一個線程,監(jiān)視某個目錄,一旦目錄里出現(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;
}
//如果這個目錄里 還有目錄,可以在這加判斷
//這里假設(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;
}
- 14:56
- 評論 / 瀏覽 (0 / 18)
- 分類:編程語言
Linux下的C編程實戰(zhàn)之文件系統(tǒng)編程
linuxc編程 1.Linux文件系統(tǒng)Linux支持多種文件系統(tǒng),如ext、ext2、minix、iso9660、msdos、fat、vfat、nfs等。在這些具體文件系統(tǒng)的上層,Linux提供了虛擬文件系統(tǒng)(VFS)來統(tǒng)一它們的行為,虛擬文件系統(tǒng)為不同的文件系統(tǒng)與內(nèi)核的通信提供了一致的接口。
linux下的c語言開發(fā)
在Linux平臺下對文件編程可以使用兩類函數(shù):(1)Linux操作系統(tǒng)文件API;(2)C語言I/O庫函數(shù)。 前者依賴于Linux系統(tǒng)調(diào)用,后者實際上與操作系統(tǒng)是獨(dú)立的,因為在任何操作系統(tǒng)下,使用C語言I/O庫函數(shù)操作文件的方法都是相同的。本章將對這兩種方法進(jìn)行實例講解。
2.Linux文件API
Linux的文件操作API涉及到創(chuàng)建、打開、讀寫和關(guān)閉文件。
創(chuàng)建
int creat(const char *filename, mode_t mode);
參數(shù)mode指定新建文件的存取權(quán)限,它同umask一起決定文件的最終權(quán)限(mode&umask),其中umask代表了文件在創(chuàng)建時需要去掉的一些存取權(quán)限。umask可通過系統(tǒng)調(diào)用umask()來改變:
int umask(int newmask);
該調(diào)用將umask設(shè)置為newmask,然后返回舊的umask,它只影響讀、寫和執(zhí)行權(quán)限。
打開
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
open函數(shù)有兩個形式,其中pathname是我們要打開的文件名(包含路徑名稱,缺省是認(rèn)為在當(dāng)前路徑下面),flags可以去下面的一個值或者是幾個值的組合:
標(biāo)志 含義
O_RDONLY 以只讀的方式打開文件
O_WRONLY 以只寫的方式打開文件
O_RDWR 以讀寫的方式打開文件
O_APPEND 以追加的方式打開文件
O_CREAT 創(chuàng)建一個文件
O_EXEC 如果使用了O_CREAT而且文件已經(jīng)存在,就會發(fā)生一個錯誤
O_NOBLOCK 以非阻塞的方式打開一個文件
O_TRUNC 如果文件已經(jīng)存在,則刪除文件的內(nèi)容
O_RDONLY、O_WRONLY、O_RDWR三個標(biāo)志只能使用任意的一個。
如果使用了O_CREATE標(biāo)志,則使用的函數(shù)是int open(const char *pathname,int flags,mode_t mode); 這個時候我們還要指定mode標(biāo)志,用來表示文件的訪問權(quán)限。mode可以是以下情況的組合:
標(biāo)志 含義
S_IRUSR 用戶可以讀
S_IWUSR 用戶可以寫
S_IXUSR 用戶可以執(zhí)行
S_IRWXU 用戶可以讀、寫、執(zhí)行
S_IRGRP 組可以讀
S_IWGRP 組可以寫
S_IXGRP 組可以執(zhí)行
S_IRWXG 組可以讀寫執(zhí)行
S_IROTH 其他人可以讀
S_IWOTH 其他人可以寫
S_IXOTH 其他人可以執(zhí)行
S_IRWXO 其他人可以讀、寫、執(zhí)行
S_ISUID 設(shè)置用戶執(zhí)行ID
S_ISGID 設(shè)置組的執(zhí)行ID
除了可以通過上述宏進(jìn)行“或”邏輯產(chǎn)生標(biāo)志以外,我們也可以自己用數(shù)字來表示,Linux總共用5個數(shù)字來表示文件的各種權(quán)限:第一位表示設(shè)置用戶ID;第二位表示設(shè)置組ID;第三位表示用戶自己的權(quán)限位;第四位表示組的權(quán)限;最后一位表示其他人的權(quán)限。每個數(shù)字可以取1(執(zhí)行權(quán)限)、2(寫權(quán)限)、4(讀權(quán)限)、0(無)或者是這些值的和。例如,要創(chuàng)建一個用戶可讀、可寫、可執(zhí)行,但是組沒有權(quán)限,其他人可以讀、可以執(zhí)行的文件,并設(shè)置用戶ID位。那么,我們應(yīng)該使用的模式是1(設(shè)置用戶ID)、0(不設(shè)置組 ID)、7(1+2+4,讀、寫、執(zhí)行)、0(沒有權(quán)限)、5(1+4,讀、執(zhí)行)即10705:
open("test", O_CREAT, 10705);
上述語句等價于:
open("test", O_CREAT, S_IRWXU | S_IROTH | S_IXOTH | S_ISUID );
如果文件打開成功,open函數(shù)會返回一個文件描述符,以后對該文件的所有操作就可以通過對這個文件描述符進(jìn)行操作來實現(xiàn)。
讀寫
在文件打開以后,我們才可對文件進(jìn)行讀寫了,Linux中提供文件讀寫的系統(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()實現(xiàn)從文件描述符fd所指定的文件中讀取 length個字節(jié)到buf所指向的緩沖區(qū)中,返回值為實際讀取的字節(jié)數(shù)。函數(shù)write實現(xiàn)將把length個字節(jié)從buf指向的緩沖區(qū)中寫到文件描述符fd所指向的文件中,返回值為實際寫入的字節(jié)數(shù)。
以O(shè)_CREAT為標(biāo)志的open實際上實現(xiàn)了文件創(chuàng)建的功能,因此,下面的函數(shù)等同creat()函數(shù):
int open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
定位
對于隨機(jī)文件,我們可以隨機(jī)的指定位置讀寫,使用如下函數(shù)進(jìn)行定位:
int lseek(int fd, offset_t offset, int whence);
lseek()將文件讀寫指針相對whence移動offset個字節(jié)。操作成功時,返回文件指針相對于文件頭的位置。參數(shù)whence可使用下述值:
SEEK_SET:相對文件開頭
SEEK_CUR:相對文件讀寫指針的當(dāng)前位置
SEEK_END:相對文件末尾
offset可取負(fù)值,例如下述調(diào)用可將文件指針相對當(dāng)前位置向前移動5個字節(jié):
lseek(fd, -5, SEEK_CUR);
由于lseek函數(shù)的返回值為文件指針相對于文件頭的位置,因此下列調(diào)用的返回值就是文件的長度:
lseek(fd, 0, SEEK_END);
關(guān)閉
當(dāng)我們操作完成以后,我們要關(guān)閉文件了,只要調(diào)用close就可以了,其中fd是我們要關(guān)閉的文件描述符:
int close(int fd);
例程:編寫一個程序,在當(dāng)前目錄下創(chuàng)建用戶可讀寫文件“hello.txt”,在其中寫入“Hello, software weekly”,關(guān)閉該文件。再次打開該文件,讀取其中的內(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)建并打開文件 */
if (fd)
{
write(fd, "Hello, Software Weekly", strlen("Hello, software weekly")); /* 寫入 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語言庫函數(shù)
C庫函數(shù)的文件操作實際上是獨(dú)立于具體的操作系統(tǒng)平臺的,不管是在DOS、Windows、Linux還是在VxWorks中都是這些函數(shù):
創(chuàng)建和打開
FILE *fopen(const char *path, const char *mode);
fopen()實現(xiàn)打開指定文件filename,其中的mode為打開模式,C語言中支持的打開模式如下表:
標(biāo)志 含義
r, rb 以只讀方式打開
w, wb 以只寫方式打開。如果文件不存在,則創(chuàng)建該文件,否則文件被截斷
a, ab 以追加方式打開。如果文件不存在,則創(chuàng)建該文件
r+, r+b, rb+ 以讀寫方式打開
w+, w+b, wh+ 以讀寫方式打開。如果文件不存在時,創(chuàng)建新文件,否則文件被截斷
a+, a+b, ab+ 以讀和追加方式打開。如果文件不存在,創(chuàng)建新文件
其中b用于區(qū)分二進(jìn)制文件和文本文件,這一點在DOS、Windows系統(tǒng)中是有區(qū)分的,但Linux不區(qū)分二進(jìn)制文件和文本文件。
讀寫
C庫函數(shù)支持以字符、字符串等為單位,支持按照某中格式進(jìn)行文件的讀寫,這一組函數(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()實現(xiàn)從流stream中讀取加n個字段,每個字段為size字節(jié),并將讀取的字段放入ptr所指的字符數(shù)組中,返回實際已讀取的字段數(shù)。在讀取的字段數(shù)小于num時,可能是在函數(shù)調(diào)用時出現(xiàn)錯誤,也可能是讀到文件的結(jié)尾。所以要通過調(diào)用feof()和ferror()來判斷。
write()實現(xiàn)從緩沖區(qū)ptr所指的數(shù)組中把n個字段寫到流stream中,每個字段長為size個字節(jié),返回實際寫入的字段數(shù)。
另外,C庫函數(shù)還提供了讀寫過程中的定位能力,這些函數(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庫函數(shù)關(guān)閉文件依然是很簡單的操作:
int fclose (FILE *stream);
例程:將第2節(jié)中的例程用C庫函數(shù)來實現(xiàn)。
#include <stdio.h>
#define LENGTH 100
main()
{
FILE *fd;
char str[LENGTH];
fd = fopen("hello.txt", "w+"); /* 創(chuàng)建并打開文件 */
if (fd)
{
fputs("Hello, Software Weekly", fd); /* 寫入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庫函數(shù)。這兩種編程所涉及到文件操作有新建、打開、讀寫和關(guān)閉,對隨機(jī)文件還可以定位。本章對這兩種編程方法都給出了具體的實例。
- 14:00
- 評論 / 瀏覽 (0 / 19)
- 分類:編程語言
基本IO函數(shù)的使用(open,write,read)(一)
linux c 首先感謝作者的工作,謝謝了,轉(zhuǎn)到這里都是我需要過的=>#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
摘要:本文簡單介紹文件操作的三個函數(shù)(open,read,write)的基本用法。
詳細(xì)說明了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ù)說明:
參數(shù) pathname 指向欲打開的文件路徑字符串。下列是參數(shù) flags 所能使用的旗標(biāo):
O_RDONLY 以只讀方式打開文件
O_WRONLY 以只寫方式打開文件
O_RDWR以可讀寫方式打開文件。
上述三種旗標(biāo)是互斥的,也就是不可同時使用,但可與下列的旗標(biāo)利用 OR(|)運(yùn)算符組合。
O_CREAT 若欲打開的文件不存在則自動建立該文件。
O_EXCL 如果 O_CREAT 也被設(shè)置, 此指令會去檢查文件是否存在。文件若不存在則建立該文件,
否則將導(dǎo)致打開文件錯誤。 此外,若 O_CREAT 與 O_EXCL 同時設(shè)置, 并且欲打開的文件為符號連接,則會打開文件失敗。
O_NOCTTY 如果欲打開的文件為終端機(jī)設(shè)備時,則不會將該終端機(jī)當(dāng)成進(jìn)程控制終端機(jī)。
O_TRUNC 若文件存在并且以可寫的方式打開時,此旗標(biāo)會令文件長度清為 0,而原來存于該文件的資料也會消失。
O_APPEND 當(dāng)讀寫文件時會從文件尾開始移動, 也就是所寫入的數(shù)據(jù)會以附加的方式加入到文件后面。
O_NONBLOCK 以不可阻斷的方式打開文件,也就是無論有無數(shù)據(jù)讀取或等待,都會立即返回進(jìn)程之中。
O_NDELAY 同 O_NONBLOCK。
O_SYNC 以同步的方式打開文件。
O_NOFOLLOW 如果參數(shù) pathname 所指的文件為一符號連接,則會令打開文件失敗。
O_DIRECTORY 如果參數(shù) pathname 所指的文件并非為一目錄, 則
會令打開文件失敗。此為 Linux2.2 以后特有的旗標(biāo),以避免一些系
統(tǒng)安全問題。參數(shù) mode 則有下列數(shù)種組合,只有在建立新文件時
才會生效,此外真正建文件時的權(quán)限會受到 umask 值所影響,因此
該文件權(quán)限應(yīng)該為(mode-umaks).
S_IRWXU00700 權(quán)限, 代表該文件所有者具有可讀、 可寫及可執(zhí)行的權(quán)限。
S_IRUSR 或 S_IREAD,00400 權(quán)限,代表該文件所有者具有可讀取的權(quán)限。
S_IWUSR 或 S_IWRITE,00200 權(quán)限,代表該文件所有者具有可寫入的權(quán)限。
S_IXUSR 或 S_IEXEC,00100 權(quán)限,代表該文件所有者具有可執(zhí)行的權(quán)限。
S_IRWXG 00070 權(quán)限,代表該文件用戶組具有可讀、 可寫及可執(zhí)行的權(quán)限。
S_IRGRP 00040 權(quán)限,代表該文件用戶組具有可讀的權(quán)限。
S_IWGRP 00020 權(quán)限,代表該文件用戶組具有可寫入的權(quán)限。
S_IXGRP 00010 權(quán)限,代表該文件用戶組具有可執(zhí)行的權(quán)限。
S_IRWXO 00007 權(quán)限,代表其他用戶具有可讀、可寫及可執(zhí)行的權(quán)限。
S_IROTH 00004 權(quán)限,代表其他用戶具有可讀的權(quán)限
S_IWOTH 00002 權(quán)限,代表其他用戶具有可寫入的權(quán)限。
S_IXOTH 00001 權(quán)限,代表其他用戶具有可執(zhí)行的權(quán)限。
返回值:
若所有欲核查的權(quán)限都通過了檢查則返回 0 值,表示成功,只要有 一個權(quán)限被禁止則返回-1。
錯誤代碼:
EEXIST 參數(shù) pathname 所指的文件已存在,卻使用了 O_CREAT和 O_EXCL 旗標(biāo)
EACCESS 參數(shù) pathname 所指的文件不符合所要求測試的權(quán)限。
EROFS 欲測試寫入權(quán)限的文件存在于只讀文件系統(tǒng)內(nèi)。
EFAULT 參數(shù) pathname 指針超出可存取內(nèi)存空間。
EINVAL 參數(shù) mode 不正確。
ENAMETOOLONG 參數(shù) pathname 太長。
ENOTDIR 參數(shù) pathname 不是目錄。
ENOMEM 核心內(nèi)存不足。
ELOOP 參數(shù) pathname 有過多符號連接問題。
EIO I/O 存取錯誤。
范例:
#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 );//以可讀寫的方式打開一個文件,如果不存在則創(chuàng)建該文件
if ( -1 == fd )
{
printf("Open or create file named \"temp.log\" failed.\n");
return -1;
}
write( fd, s, sizeof(s) );//向該文件中寫入一個字符串
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ù)組中,返回讀取的字符個數(shù)
close( fd );
printf( "%s", buffer );
return 0;
}
- 13:44
- 評論 / 瀏覽 (0 / 3)
- 分類:編程語言
Android讀寫文件
android 一、 從resource中的raw文件夾中獲取文件并讀取數(shù)據(jù)(資源文件只能讀不能寫)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)整會亂碼
in.close();
}catch(Exception e){
e.printStackTrace();
}
myTextView.setText(res);//把得到的內(nèi)容顯示在TextView上
二、 從asset中獲取文件并讀取數(shù)據(jù)(資源文件只能讀不能寫)
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中去讀文件,首先要把文件通過\android-sdk-windows\tools\adb.exe把本地計算機(jī)上的文件copy到sdcard上去,adb.exe push e:/Y.txt /sdcard/, 不可以用adb.exe push e:\Y.txt \sdcard\ 同樣: 把仿真器上的文件copy到本地計算機(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);
//用這個就不行了,必須用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);
四、 寫文件, 一般寫在\data\data\com.test\files\里面,打開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();
}
}
五、 寫, 讀data/data/目錄(相當(dāng)AP工作目錄)上的文件,用openFileOutput
//寫文件在./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;
}
六、 寫, 讀sdcard目錄上的文件,要用FileOutputStream, 不能用openFileOutput
//寫在/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里編譯過的,FileOutputStream是任何文件都可以
參考:http://dev.10086.cn/cmdn/wiki/index.php?doc-view-6017.html
- 12:12
- 評論 / 瀏覽 (0 / 30)
- 分類:移動開發(fā)
ASCII Characters 對照表
asc asc碼對照表-------------------------------------------------------------
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ī)中用得最廣泛的字符集及其編碼,是由美國國家標(biāo)準(zhǔn)局(ANSI)制定的ASCII碼(American Standard Code for Information Interchange,美國標(biāo)準(zhǔn)信息交換碼),它已被國際標(biāo)準(zhǔn)化組織(ISO)定為國際標(biāo)準(zhǔn),稱為ISO 646標(biāo)準(zhǔn)。適用于所有拉丁文字字母,ASCII碼有7位碼和8位碼兩種形式。
因為1位二進(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)都唯一地編為一個7位的二進(jìn)制碼,對應(yīng)一個字符(或控制碼),這些碼可以排列成一個十進(jìn)制序號0~127。所以,7位 ASCII碼是用七位二進(jìn)制數(shù)進(jìn)行編碼的,可以表示128個字符。
第0~32號及第127號(共34個)是控制字符或通訊專用字符,如控制符:LF(換行)、CR(回車)、FF(換頁)、DEL(刪除)、BEL(振鈴)等;通訊專用字符:SOH(文頭)、EOT(文尾)、ACK(確認(rèn))等;
第33~126號(共94個)是字符,其中第48~57號為0~9十個阿拉伯?dāng)?shù)字;65~90號為26個大寫英文字母,97~122號為26個小寫英文字母,其余為一些標(biāo)點符號、運(yùn)算符號等。
注意:在計算機(jī)的存儲單元中,一個ASCII碼值占一個字節(jié)(8個二進(jìn)制位),其最高位(b7)用作奇偶校驗位。所謂奇偶校驗,是指在代碼傳送過程中用來檢驗是否出現(xiàn)錯誤的一種方法,一般分奇校驗和偶校驗兩種。奇校驗規(guī)定:正確的代碼一個字節(jié)中1的個數(shù)必須是奇數(shù),若非奇數(shù),則在最高位b7添1;偶校驗規(guī)定:正確的代碼一個字節(jié)中1的個數(shù)必須是偶數(shù),若非偶數(shù),則在最高位b7添1。
第128~255號為擴(kuò)展字符(不常用),如需要請下載:完整的8位ASCII字符表
- 09:36
- 評論 / 瀏覽 (0 / 7)
- 分類:非技術(shù)
Android輸入事件流程中的EventHub分析及源碼演示
android Android2.3的輸入事件流程與以前版本有了較大的不同,這里做一下詳細(xì)的分析,最后我把自己分析時用的演示代碼放在了這里:http://code.google.com/p/flying-on-android/
下面的分析都是基于這些源碼的,大家可以下載下來一邊看源碼一邊看文檔。源碼里只要關(guān)注FlyingEvent這個類就可以了。如果只想看一下演示結(jié)果,可以直接把包里的flying放到機(jī)器的/system/bin目錄執(zhí)行,打開logcat后就可以看到演示輸出。運(yùn)行程序時,機(jī)器屏幕會有異象產(chǎn)生,很正常,因為這個程序原本是用于顯示SurfaceFlinger的,這次為了演示EventHub稍微改了一下。大家只要關(guān)注 FlyingEvent.cpp這個文件就好了。
大家也可以用源碼自己編譯出演示程序,只要把解壓后的flying文件夾放到/frameworks/base/cmds/目錄下,然后切換到flying目錄下使用mm編譯。
先大致介紹一下整個流程,再做重點分析。輸入事件流程一共涉及到下面這幾個文件:
/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主要用來讀取設(shè)備文件中的RawEvent,而InputReader.cpp和InputDispatcher.cpp算是它們之間的對接層。
它們的關(guān)系是:WindowManagerService通過InputManager提供的接口開啟一個線程驅(qū)動InputReader不斷地從 /dev/input/目錄下面的設(shè)備文件讀取事件,然后通過InputDispatcher分發(fā)給連接到WindowManagerService服務(wù)的客戶端。
InputReader從設(shè)備文件中讀取的是RawEvent,在交給InputDispatcher進(jìn)行分發(fā)之前,它需要先把RawEvent進(jìn)行轉(zhuǎn)化分類,拆分成KeyEvent、MotionEvent、TrackEvent各種類型等。這篇文章主要關(guān)注的就是這個RawEvent的拆分過程,所以我們的重點在EventHub.cpp中。并且,為了簡單化分析過程,在這里我的分析只關(guān)注觸摸屏事件。看它是如何從RawEvent被拆分成應(yīng)用層用戶事件MotionEvent的。
看下面的分析之前,最好先去上面提到的地址把源碼下載下來,參照里面的FlyingEvent.cpp。
整個過程大致分成這么幾步:
一、初始化。
先new一個EventHub的實例:mEventHub(new EventHub),
接下來,開啟一個線程通過mEventHub不停地從設(shè)備文件中讀取RawEvent并處理:
while (1) {
RawEvent event;
mEventHub->getEvent(&event);
process(event);
}
EventHub在初始化的時候做一些事情,
1、搜索當(dāng)前的輸入設(shè)備每搜索到一個就會產(chǎn)生一個類型為DEVICE_ADDED的事件,當(dāng)讀取這種RawEvent時,InputReader會把搜索到的這個設(shè)備記錄下來。
2、如果搜索到了鍵盤時,就會加載鍵盤布局文件。加載完成后產(chǎn)生一個類型為FINISHED_DEVICE_SCAN的事件。這樣,后邊從驅(qū)動讀取用戶按鍵時,就會去加載的鍵盤布局文件中尋找映射的鍵值封裝成KeyEvent返回給用戶。
二、EventHub初始化完畢后,就開始等待用戶輸入。線程一直阻塞在mEventHub->getEvent(&event),直到有用戶事件產(chǎn)生才會返回。
當(dāng)有一個事件產(chǎn)生時,傳遞給process進(jìn)行處理。
三、事件拆分
FlyingEvent.process里面主要調(diào)用了FlyingEvent.consume方法來處理用戶事件。這里只分析touch事件。touch事件可以分為三種:down,move,up。
down類型的touch事件需要四個RawEvent來完成,第一個是X坐標(biāo)(ABS_X),第二個是Y坐標(biāo)(ABS_Y),第三個代表方向(ABS_PRESSURE)(0的時候是up,1的時候是down,所以這里應(yīng)該是1),第四個是結(jié)束標(biāo)志(SYN_REPORT)。
move類型的touch事件需要三個RawEvent來完成,第一個是X坐標(biāo),第二個是Y坐標(biāo),第三個是結(jié)束標(biāo)志。
up類型的touch事件需要兩個RawEvent來完成,第一個代表方向(0的時候是up,1的時候是down,所以這里應(yīng)該是0),第四個是結(jié)束標(biāo)志。
可能你已經(jīng)注意到了up事件是沒有坐標(biāo)信息的,它的坐標(biāo)信息與down(沒有move時)或最后一個move(down和up之間有move事件產(chǎn)生)事件的坐標(biāo)相同。
從FlyingEvent.consume方法中,每一個事件最終都會生成一個TouchEvent,然后調(diào)用printTouchEvent進(jìn)行打印,最后把它存儲到eventBuffer中。
參考文章
李先靜的“Android輸入事件流程“,不過使用的Android版本比較老了。
http://blog.csdn.net/absurd/archive/2009/05/17/4195363.aspx
(摘自:http://blog.csdn.net/a345017062/article/details/6417929)
- 19:58
- 評論 / 瀏覽 (0 / 35)
- 分類:移動開發(fā)
svn還原恢復(fù)
svn 1.對文件和目錄的修改還原svn revert PATH...
描述
恢復(fù)所有對文件和目錄的修改,并且解決所有的沖突狀態(tài)。svn revert不會只是恢復(fù)工作拷貝中一個項目的內(nèi)容,也包括了對屬性修改的恢復(fù)。最終,你可以使用它來取消所有已經(jīng)做過的預(yù)定操作(例如,文件預(yù)定要添加或刪除可以“恢復(fù)”)。
例子
丟棄對一個文件的修改:
$ svn revert foo.c
Reverted foo.c
如果你希望恢復(fù)一整個目錄的文件,可以使用--recursive選項:
$ svn revert --recursive .
Reverted newdir/afile
Reverted foo.c
Reverted bar.txt
2.還原到以前版本
svn update -r 200 test.php(將版本庫中的文件test.php還原到版本200)
3.列出本地與SVN當(dāng)前版本差異
svn status -v path(顯示文件和子目錄狀態(tài))
簡寫:svn st
第一列保持相同,第二列顯示工作版本號,第三和第四列顯示最后一次修改的版本號和修改人。
另外,可執(zhí)行script -q tty.log后,就開始記錄終端的輸入輸出信息,結(jié)束的時候按ctrl+D即可得到終端的內(nèi)容文件tty.log
4. svn比較差異
svn diff path(將修改的文件與基礎(chǔ)版本比較)
例如:svn diff test.php
svn diff -r m:n path(對版本m和版本n比較差異)
注:svn status、svn diff和 svn revert這三條命令在沒有網(wǎng)絡(luò)的情況下也可以執(zhí)行的,原因是svn在本地的.svn中保留了本地版本的原始拷貝。
- 11:19
- 評論 / 瀏覽 (0 / 43)
- 分類:非技術(shù)
linux下查看內(nèi)存使用情況
在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
下面是對這些數(shù)值的解釋:
total:總計物理內(nèi)存的大小。
used:已使用多大。
free:可用有多少。
Shared:多個進(jìn)程共享的內(nèi)存總額。
Buffers/cached:磁盤緩存的大小。
第三行(-/+ buffers/cached):
used:已使用多大。
free:可用有多少。
第四行就不多解釋了。
區(qū)別:第二行(mem)的used/free與第三行(-/+ buffers/cache) used/free的區(qū)別。 這兩個的區(qū)別在于使用的角度來看,第一行是從OS的角度來看,因為對于OS,buffers/cached 都是屬于被使用,所以他的可用內(nèi)存是16176KB,已用內(nèi)存是3250004KB,其中包括,內(nèi)核(OS)使用+Application(X, oracle,etc)使用的+buffers+cached.
第三行所指的是從應(yīng)用程序角度來看,對于應(yīng)用程序來說,buffers/cached 是等于可用的,因為buffer/cached是為了提高文件讀取的性能,當(dāng)應(yīng)用程序需在用到內(nèi)存的時候,buffer/cached會很快地被回收。
所以從應(yīng)用程序的角度來說,可用內(nèi)存=系統(tǒng)free memory+buffers+cached。
如上例:
2795064=16176+110652+2668236
接下來解釋什么時候內(nèi)存會被交換,以及按什么方交換。 當(dāng)可用內(nèi)存少于額定值的時候,就會開會進(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)存的測量
測量一個進(jìn)程占用了多少內(nèi)存,linux為我們提供了一個很方便的方法,/proc目錄為我們提供了所有的信息,實際上top等工具也通過這里來獲取相應(yīng)的信息。
/proc/meminfo 機(jī)器的內(nèi)存使用信息
/proc/pid/maps pid為進(jìn)程號,顯示當(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。。。的每行的每個參數(shù)意思(以第一行為例)為:
參數(shù) 解釋 /proc//status
Size (pages) 任務(wù)虛擬地址空間的大小 VmSize/4
Resident(pages) 應(yīng)用程序正在使用的物理內(nèi)存的大小 VmRSS/4
Shared(pages) 共享頁數(shù) 0
Trs(pages) 程序所擁有的可執(zhí)行虛擬內(nèi)存的大小 VmExe/4
Lrs(pages) 被映像到任務(wù)的虛擬內(nèi)存空間的庫的大小 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
我們通過free命令查看機(jī)器空閑內(nèi)存時,會發(fā)現(xiàn)free的值很小。這主要是因為,在linux中有這么一種思想,內(nèi)存不用白不用,因此它盡可能的cache和buffer一些數(shù)據(jù),以方便下次使用。但實際上這些內(nèi)存也是可以立刻拿來使用的。
所以 空閑內(nèi)存=free+buffers+cached=total-used
- 17:52
- 評論 / 瀏覽 (0 / 13)
- 分類:操作系統(tǒng)
android 鏡像制作方法
android 一:update.zip包的制作1:新建一個目標(biāo),在此目錄下準(zhǔn)備好需要的文件,如system目錄文件、boot.img、recovery.img等.
mkdir testupdate
cp system/ testupdate/ -tf
注:如果文件是system.img鏡像可以用unyaffs解壓出來得到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)修改些腳本
說明:system是要更新的目錄,android-info.txt是板的版本信息,update-script是輸出文件名
3:建立一個目錄名稱為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根目錄下去驗證吧!
注意:
1)如果文件里有連接,應(yīng)該在獲取update-script之后在原文件里刪除鏈接文件,再打包,否則symlink將出錯;
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
這里需要驗證哪個能用android寫下去
三: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)部分時候可以如第四所示范
2:如果recovery為ramdisk形式
=============================================
制 作ramdisk的過程。
1.在/mnt下創(chuàng)建rdmnt 和 rdimg 目錄
mkdir rdmnt
mkdir rdimg
2.創(chuàng)建一個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
- 16:30
- 評論 / 瀏覽 (0 / 94)
- 分類:移動開發(fā)
Eclipse下svn屬性設(shè)置
androidframeworks 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
- 16:52
- 評論 / 瀏覽 (0 / 83)
- 分類:移動開發(fā)
linux/Unix環(huán)境下的make和makefile詳解
makelinux腳本 無論是在linux還是在Unix環(huán)境中,make都是一個非常重要的編譯命令。不管是自己進(jìn)行項目開發(fā)還是安裝應(yīng)用軟件,我們都經(jīng)常要用到make或make install。利用make工具,我們可以將大型的開發(fā)項目分解成為多個更易于管理的模塊,對于一個包括幾百個源文件的應(yīng)用程序,使用make和 makefile工具就可以簡潔明快地理順各個源文件之間紛繁復(fù)雜的相互關(guān)系。而且如此多的源文件,如果每次都要鍵入gcc命令進(jìn)行編譯的話,那對程序員來說簡直就是一場災(zāi)難。而make工具則可自動完成編譯工作,并且可以只對程序員在上次編譯后修改過的部分進(jìn)行編譯。因此,有效的利用make和 makefile工具可以大大提高項目開發(fā)的效率。同時掌握make和makefile之后,您也不會再面對著Linux下的應(yīng)用軟件手足無措了。但令人遺憾的是,在許多講述linux應(yīng)用的書籍上都沒有詳細(xì)介紹這個功能強(qiáng)大但又非常復(fù)雜的編譯工具。在這里我就向大家詳細(xì)介紹一下make及其描述文件makefile。
Makefile文件
Make工具最主要也是最基本的功能就是通過makefile文件來描述源程序之間的相互關(guān)系并自動維護(hù)編譯工作。而makefile 文件需要按照某種語法進(jìn)行編寫,文件中需要說明如何編譯各個源文件并連接生成可執(zhí)行文件,并要求定義源文件之間的依賴關(guān)系。makefile 文件是許多編譯器--包括 Windows NT 下的編譯器--維護(hù)編譯信息的常用方法,只是在集成開發(fā)環(huán)境中,用戶通過友好的界面修改 makefile 文件而已。
在 UNIX 系統(tǒng)中,習(xí)慣使用 Makefile 作為 makfile 文件。如果要使用其他文件作為 makefile,則可利用類似下面的 make 命令選項指定 makefile 文件:
$ make -f Makefile.debug
例如,一個名為prog的程序由三個C源文件filea.c、fileb.c和filec.c以及庫文件LS編譯生成,這三個文件還分別包含自己的頭文件a.h 、b.h和c.h。通常情況下,C編譯器將會輸出三個目標(biāo)文件filea.o、fileb.o和filec.o。假設(shè)filea.c和fileb.c都要聲明用到一個名為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
----------------------------------------------------------
這個描述文檔就是一個簡單的makefile文件。
從上面的例子注意到,第一個字符為 # 的行為注釋行。第一個非注釋行指定prog由三個目標(biāo)文件filea.o、fileb.o和filec.o鏈接生成。第三行描述了如何從prog所依賴的文件建立可執(zhí)行文件。接下來的4、6、8行分別指定三個目標(biāo)文件,以及它們所依賴的.c和.h文件以及defs文件。而5、7、9行則指定了如何從目標(biāo)所依賴的文件建立目標(biāo)。
當(dāng)filea.c或a.h文件在編譯之后又被修改,則 make 工具可自動重新編譯filea.o,如果在前后兩次編譯之間,filea.C 和a.h 均沒有被修改,而且 test.o 還存在的話,就沒有必要重新編譯。這種依賴關(guān)系在多源文件的程序編譯中尤其重要。通過這種依賴關(guān)系的定義,make 工具可避免許多不必要的編譯工作。當(dāng)然,利用 Shell 腳本也可以達(dá)到自動編譯的效果,但是,Shell 腳本將全部編譯任何源文件,包括哪些不必要重新編譯的源文件,而 make 工具則可根據(jù)目標(biāo)上一次編譯的時間和目標(biāo)所依賴的源文件的更新時間而自動判斷應(yīng)當(dāng)編譯哪個源文件。
Makefile文件作為一種描述文檔一般需要包含以下內(nèi)容:
◆ 宏定義
◆ 源文件之間的相互依賴關(guān)系
◆ 可執(zhí)行的命令
Makefile中允許使用簡單的宏指代源文件及其相關(guān)編譯信息,在linux中也稱宏為變量。在引用宏時只需在變量前加$符號,但值得注意的是,如果變量名的長度超過一個字符,在引用時就必須加圓括號()。
下面都是有效的宏引用:
$(CFLAGS)
$2
$Z
$(Z)
其中最后兩個引用是完全一致的。
需要注意的是一些宏的預(yù)定義變量,在Unix系統(tǒng)中,$*、$@、$?和$<四個特殊宏的值在執(zhí)行命令的過程中會發(fā)生相應(yīng)的變化,而在GNU make中則定義了更多的預(yù)定義變量。關(guān)于預(yù)定義變量的詳細(xì)內(nèi)容,
宏定義的使用可以使我們脫離那些冗長乏味的編譯選項,為編寫makefile文件帶來很大的方便。
---------------------------------------------------------
# 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
……
---------------------------------------------------------
此時如果執(zhí)行不帶參數(shù)的make命令,將連接三個目標(biāo)文件和庫文件LS;但是如果在make命令后帶有新的宏定義:
make "LIBES= -LL -LS"
則命令行后面的宏定義將覆蓋makefile文件中的宏定義。若LL也是庫文件,此時make命令將連接三個目標(biāo)文件以及兩個庫文件LS和LL。
在Unix系統(tǒng)中沒有對常量NULL作出明確的定義,因此我們要定義NULL字符串時要使用下述宏定義:
STRINGNAME=
Make命令
在make命令后不僅可以出現(xiàn)宏定義,還可以跟其他命令行參數(shù),這些參數(shù)指定了需要編譯的目標(biāo)文件。其標(biāo)準(zhǔn)形式為:
target1 [target2 …]:[:][dependent1 …][;commands][#…]
[(tab) commands][#…]
方括號中間的部分表示可選項。Targets和dependents當(dāng)中可以包含字符、數(shù)字、句點和"/"符號。除了引用,commands中不能含有"#",也不允許換行。
在通常的情況下命令行參數(shù)中只含有一個":",此時command序列通常和makefile文件中某些定義文件間依賴關(guān)系的描述行有關(guān)。如果與目標(biāo)相關(guān)連的那些描述行指定了相關(guān)的command序列,那么就執(zhí)行這些相關(guān)的command命令,即使在分號和(tab)后面的aommand字段甚至有可能是NULL。如果那些與目標(biāo)相關(guān)連的行沒有指定command,那么將調(diào)用系統(tǒng)默認(rèn)的目標(biāo)文件生成規(guī)則。
如果命令行參數(shù)中含有兩個冒號"::",則此時的command序列也許會和makefile中所有描述文件依賴關(guān)系的行有關(guān)。此時將執(zhí)行那些與目標(biāo)相關(guān)連的描述行所指向的相關(guān)命令。同時還將執(zhí)行build-in規(guī)則。
如果在執(zhí)行command命令時返回了一個非"0"的出錯信號,例如makefile文件中出現(xiàn)了錯誤的目標(biāo)文件名或者出現(xiàn)了以連字符打頭的命令字符串,make操作一般會就此終止,但如果make后帶有"-i"參數(shù),則make將忽略此類出錯信號。
Make命本身可帶有四種參數(shù):標(biāo)志、宏定義、描述文件名和目標(biāo)文件名。其標(biāo)準(zhǔn)形式為:
Make [flags] [macro definitions] [targets]
Unix系統(tǒng)下標(biāo)志位flags選項及其含義為:
-f file 指定file文件為描述文件,如果file參數(shù)為"-"符,那么描述文件指向標(biāo)準(zhǔn)輸入。如果沒有"-f"參數(shù),則系統(tǒng)將默認(rèn)當(dāng)前目錄下名為 makefile或者名為Makefile的文件為描述文件。在linux中, GNU make 工具在當(dāng)前工作目錄中按照GNUmakefile、makefile、Makefile的順序搜索 makefile文件。
-i 忽略命令執(zhí)行返回的出錯信息。
-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)文件和檢測時間的詳細(xì)信息。
linux下make標(biāo)志位的常用選項與Unix系統(tǒng)中稍有不同,下面我們只列出了不同部分:
-c dir 在讀取 makefile 之前改變到指定的目錄dir。
-I dir 當(dāng)包含其他 makefile文件時,利用該選項指定搜索目錄。
-h help文擋,顯示所有的make選項。
-w 在處理 makefile 之前和之后,都顯示工作目錄。
通過命令行參數(shù)中的target ,可指定make要編譯的目標(biāo),并且允許同時定義編譯多個目標(biāo),操作時按照從左向右的順序依次編譯target選項中指定的目標(biāo)文件。如果命令行中沒有指定目標(biāo),則系統(tǒng)默認(rèn)target指向描述文件中第一個目標(biāo)文件。
通常,makefile 中還定義有 clean 目標(biāo),可用來清除編譯過程中的中間文件,例如:
clean:
rm -f *.o
運(yùn)行 make clean 時,將執(zhí)行 rm -f *.o 命令,最終刪除所有編譯過程中產(chǎn)生的所有中間文件。
隱含規(guī)則
在make 工具中包含有一些內(nèi)置的或隱含的規(guī)則,這些規(guī)則定義了如何從不同的依賴文件建立特定類型的目標(biāo)。Unix系統(tǒng)通常支持一種基于文件擴(kuò)展名即文件名后綴的隱含規(guī)則。這種后綴規(guī)則定義了如何將一個具有特定文件名后綴的文件(例如.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源語法
.l Lex源語法
在早期的Unix系統(tǒng)系統(tǒng)中還支持Yacc-C源語法和Lex源語法。在編譯過程中,系統(tǒng)會首先在makefile文件中尋找與目標(biāo)文件相關(guān)的.C文件,如果還有與之相依賴的.y和.l文件,則首先將其轉(zhuǎn)換為.c文件后再編譯生成相應(yīng)的.o文件;如果沒有與目標(biāo)相關(guān)的.c文件而只有相關(guān)的.y文件,則系統(tǒng)將直接編譯.y文件。
而GNU make 除了支持后綴規(guī)則外還支持另一種類型的隱含規(guī)則--模式規(guī)則。這種規(guī)則更加通用,因為可以利用模式規(guī)則定義更加復(fù)雜的依賴性規(guī)則。模式規(guī)則看起來非常類似于正則規(guī)則,但在目標(biāo)名稱的前面多了一個 % 號,同時可用來定義目標(biāo)和依賴文件之間的關(guān)系,例如下面的模式規(guī)則定義了如何將任意一個 file.c 文件轉(zhuǎn)換為 file.o 文件:
%.c:%.o
$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
#EXAMPLE#
下面將給出一個較為全面的示例來對makefile文件和make命令的執(zhí)行進(jìn)行進(jìn)一步的說明,其中make命令不僅涉及到了C源文件還包括了Yacc 語法。本例選自"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é)果而沒有相應(yīng)的命令行,是因為"@size make"命令以"@"起始,這個符號禁止打印輸出它所在的命令行。
描述文件中的最后幾條命令行在維護(hù)編譯信息方面非常有用。其中"print"命令行的作用是打印輸出在執(zhí)行過上次"make print"命令后所有改動過的文件名稱。系統(tǒng)使用一個名為print的0字節(jié)文件來確定執(zhí)行print命令的具體時間,而宏$?則指向那些在print 文件改動過之后進(jìn)行修改的文件的文件名。如果想要指定執(zhí)行print命令后,將輸出結(jié)果送入某個指定的文件,那么就可修改P的宏定義:
make print "P= cat>zap"
在linux中大多數(shù)軟件提供的是源代碼,而不是現(xiàn)成的可執(zhí)行文件,這就要求用戶根據(jù)自己系統(tǒng)的實際情況和自身的需要來配置、編譯源程序后,軟件才能使用。只有掌握了make工具,才能讓我們真正享受到到Linux這個自由軟件世界的帶給我們無窮樂趣。
另一篇,http://wiki.ubuntu.org.cn/%E8%B7%9F%E6%88%91%E4%B8%80%E8%B5%B7%E5%86%99Makefile
- 14:35
- 評論 / 瀏覽 (0 / 55)
- 分類:移動開發(fā)
envsetup.sh腳本分析
android腳本 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
}
會依次進(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)選擇以后會出現(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)過:
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 \
))
怎樣添加一個模塊
LOCAL_PATH:= $(call my-dir)
#編譯靜態(tài)庫
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)
#編譯動態(tài)庫
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)庫
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)
#使用動態(tài)庫
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)對象
LOCAL_SRC_FILES - 編譯的源文件
LOCAL_C_INCLUDES - 需要包含的頭文件目錄
LOCAL_SHARED_LIBRARIES - 鏈接時需要的外部庫
LOCAL_PRELINK_MODULE - 是否需要prelink處理
BUILD_SHARED_LIBRARY - 指明要編譯成動態(tài)庫
LOCAL_PATH - 編譯時的目錄
$(call 目錄,目錄….) 目錄引入操作符
如該目錄下有個文件夾名稱 src,則可以這樣寫 $(call src),那么就會得到 src 目錄的完整路徑
include $(CLEAR_VARS) -清除之前的一些系統(tǒng)變量
CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mk
在 build/core/config.mk 定義 CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mk
通過include 包含自定義的.mk文件(即是自定義編譯規(guī)則)或是引用系統(tǒng)其他的.mk文件(系統(tǒng)定義的編譯規(guī)則)。
LOCAL_SRC_FILES - 編譯的源文件
可以是.c, .cpp, .java, .S(匯編文件)或是.aidl等格式
不同的文件用空格隔開。如果編譯目錄子目錄,采用相對路徑,如子目錄/文件名。也可以通過$(call 目錄),指明編譯某目錄
下所有.c/.cpp/.java/.S/ .aidl文件.追加文件 LOCAL_SRC_FILES += 文件
LOCAL_C_INCLUDES - 需要包含的頭文件目錄
可以是系統(tǒng)定義路徑,也可以是相對路徑. 如該編譯目錄下有個include目錄,寫法是include/*.h
LOCAL_SHARED_LIBRARIES - 鏈接時需要的外部共享庫
LOCAL_STATIC_LIBRARIES - 鏈接時需要的外部外部靜態(tài)
LOCAL_JAVA_LIBRARIES 加入jar包
LOCAL_MODULE - 編譯的目標(biāo)對象
module 是指系統(tǒng)的 native code,通常針對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 - 指明要編譯成動態(tài)庫。
編譯的目標(biāo),用include 操作符
UILD_STATIC_LIBRARY來指明要編譯成靜態(tài)庫。
如果是java文件的話,會用到系統(tǒng)的編譯腳本host_java_library.mk,用BUILD_PACKAGE來指明。三個編譯
-------------------
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庫
./build/core/config.mk:59:BUILD_STATIC_JAVA_LIBRARY:= $(BUILD_SYSTEM)/static_java_library.mk
------------------
BUILD_HOST_JAVA_LIBRARY 編譯本機(jī)用的JAVA庫
./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)行時鏈接的方法來加速共享庫的加載,它不僅可以加快起動速度,還可以減少部分內(nèi)存開銷,
是各種Linux架構(gòu)上用于減少程序加載時間、縮短系統(tǒng)啟動時間和加快應(yīng)用程序啟動的很受歡迎的一個工具。程序運(yùn)行時的
動態(tài)鏈接尤其是重定位(relocation)的開銷對于大型系統(tǒng)來說是很大的。
動態(tài)鏈接和加載的過程開銷很大,并且在大多數(shù)的系統(tǒng)上, 函數(shù)庫并不會常常被更動, 每次程序被執(zhí)行時所進(jìn)行的鏈接
動作都是完全相同的,對于嵌入式系統(tǒng)來說尤其如此。因此,這一過程可以改在運(yùn)行時之前就可以預(yù)先處理好,即花一些時間
利用Prelink工具對動態(tài)共享庫和可執(zhí)行文件進(jìn)行處理,修改這些二進(jìn)制文件并加入相應(yīng)的重定位等信息,節(jié)約了本來在程序
啟動時的比較耗時的查詢函數(shù)地址等工作,這樣可以減少程序啟動的時間,同時也減少了內(nèi)存的耗用。
Prelink的這種做法當(dāng)然也有代價:每次更新動態(tài)共享庫時,相關(guān)的可執(zhí)行文件都需要重新執(zhí)行一遍Prelink才能保
證有效,因為新的共享庫中的符號信息、地址等很可能與原來的已經(jīng)不同了,這就是為什么 android framework代碼一改動,
這時候就會導(dǎo)致相關(guān)的應(yīng)用程序重新被編譯。
這種代價對于嵌入式系統(tǒng)的開發(fā)者來說可能稍微帶來一些復(fù)雜度,不過好在對用戶來說幾乎是可以忽略的。
--------------------
變量設(shè)置為false那么將不做prelink操作
LOCAL_PRELINK_MODULE := false
默認(rèn)是需要prlink的,同時需要在 build/core/prelink-linux-arm.map 中加入
libhellod.so 0x96000000
這個map文件好像是制定動態(tài)庫的地址的,在前面注釋上面有一些地址范圍的信息,注意庫與庫之間的間隔數(shù),
如果指定不好的話編譯的時候會提示說地址空間沖突的問題。另外,注意排序,這里要把數(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”
參考文檔:
動態(tài)庫優(yōu)化——Prelink(預(yù)連接)技術(shù)
http://www.eefocus.com/article/09-04/71629s.html
===============
LOCAL_ARM_MODE := arm
目前Android大部分都是基于Arm處理器的,Arm指令用兩種模式Thumb(每條指令兩個字節(jié))和arm指令(每條指令四個字節(jié))
LOCAL_CFLAGS += -O3 -fstrict-aliasing -fprefetch-loop-arrays
通過設(shè)定編譯器操作,優(yōu)化級別,-O0表示沒有優(yōu)化,-O1為缺省值,-O3優(yōu)化級別最高
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
總結(jié)
以上是生活随笔為你收集整理的Android系统在超级终端下必会的命令大全(adb shell命令大全)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 前端学习(1813):前端调试之微博个人
- 下一篇: Android手机证书安装