Android系統在超級終端下必會的命令大全(adb shell命令大全)

huidaoli發表於2013-08-23
1. 顯示系統中全部Android平臺: 

    android list targets 

2. 顯示系統中全部AVD(模擬器): 

    android list avd 

3. 建立AVD(模擬器): 

    android create avd --name 名稱 --target 平臺編號 

4. 啟動模擬器: 

    emulator -avd 名稱 -sdcard ~/名稱.img (-skin 1280x800) 

5. 刪除AVD(模擬器): 

    android delete avd --name 名稱 

6. 建立SDCard: 

    mksdcard 1024M ~/名稱.img 

7. AVD(模擬器)所在位置: 

    Linux(~/.android/avd)      Windows(C:\Documents and Settings\Administrator\.android\avd) 

8. 啟動DDMS: 

    ddms 

9. 顯示當前執行的全部模擬器: 

    adb devices 

10. 對某一模擬器執行命令: 

      abd -s 模擬器編號 命令 

11. 安裝應用程式: 

      adb install -r 應用程式.apk 

12. 獲取模擬器中的檔案: 

      adb pull <remote> <local> 

13. 向模擬器中寫檔案: 

      adb push <local> <remote> 

14. 進入模擬器的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 標籤名 

19. adb shell後面跟的命令主要來自: 

      原始碼\system\core\toolbox目錄和原始碼\frameworks\base\cmds目錄。 

20. 刪除系統應用: 

      adb remount (重新掛載系統分割槽,使系統分割槽重新可寫)。 

      adb shell 

      cd system/app 

      rm *.apk 

21. 獲取管理員許可權: 

      adb root 

22. 啟動Activity: 

      adb shell am start -n 包名/包名+類名(-n 類名,-a action,-d date,-m MIME-TYPE,-c category,-e 擴充套件資料,等)。 

23、釋出埠: 

    你可以設定任意的埠號,做為主機向模擬器或裝置的請求埠。如: 
adb forward tcp:5555 tcp:8000 

24、複製檔案: 

    你可向一個裝置或從一個裝置中複製檔案, 
     複製一個檔案或目錄到裝置或模擬器上: 
  adb push <source> <destination></destination></source> 
      如:adb push test.txt /tmp/test.txt 
     從裝置或模擬器上覆制一個檔案或目錄: 
     adb pull <source> <destination></destination></source> 
     如:adb pull /addroid/lib/libwebcore.so . 

25、搜尋模擬器/裝置的例項: 

     取得當前執行的模擬器/裝置的例項的列表及每個例項的狀態: 
    adb devices 

26、檢視bug報告: 
adb bugreport 
27、記錄無線通訊日誌: 

    一般來說,無線通訊的日誌非常多,在執行時沒必要去記錄,但我們還是可以通過命令,設定記錄: 
    adb shell 
    logcat -b radio 

28、獲取裝置的ID和序列號: 

     adb get-product 
     adb get-serialno 

29、訪問資料庫SQLite3 

     adb shell 
     sqlite3 

busybox 

BusyBox 是標準 Linux 工具的一個單個可執行實現。BusyBox 包含了一些簡單的工具,例如 cat 和 echo,還包含了一些更大、更復雜的工具,例如 grep、find、mount 以及 telnet。有些人將 BusyBox 稱為 Linux 工具裡的瑞士軍刀.簡單的說BusyBox就好像是個大工具箱,它整合壓縮了 Linux 的許多工具和命令。 

1、 BusyBox 的誕生 
  BusyBox 最初是由 Bruce Perens 在 1996 年為 Debian GNU/Linux 安裝盤編寫的。其目標是在一張軟盤上建立一個可引導的 GNU/Linux 系統,這可以用作安裝盤和急救盤。 
  2、busybox的用法 
  可以這樣用busybox 
  #busybox ls 
  他的功能就相當執行ls命令 
  最常用的用法是建立指向busybox的連結,不同的連結名完成不同的功能. 
  #ln -s busybox ls 
  #ln -s busybox rm 
  #ln -s busybox mkdir 
  然後分別執行這三個連結: 
  #./ls 
  #./rm 
  #./mkdir 
  就可以分別完成了ls rm 和mkdir命令的功能.雖然他們都指向同一個可執行程式busybox,但是隻要連結名不同,完成的功能就不同,很多linux網站都提供busybox的原始碼下載。 
  3、配置busybox 
  busybox的配置程式和linux核心選單配置方式簡直一模一樣.熟悉用make menuconfig方式配置linux核心的朋友很容易上手. 
  #cp busybox-1.00.tar.gz /babylinux 
  #cd /babylinux 
  #tar xvfz busybox-1.00.tar.gz 
  #cd busybox-1.00 
  #make menuconfig 
  下面是需要編譯進busybox的功能選項。 
  General Configuration應該選的選項 
  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編譯成靜態連結的可執行檔案,執行時才獨立於其他函式庫.否則必需要其他庫檔案才能執行,在單一個linux核心不能使它正常工作. 
  Installation Options 
  Don't use /usr 
  這個選項也一定要選,否則make install 後busybox將安裝在原系統的/usr下,這將覆蓋掉系統原有的命令.選擇這個選項後,make install後會在busybox目錄下生成一個叫_install的目錄,裡面有busybox和指向它的連結. 
  其它選項都是一些linux基本命令選項,自己需要哪些命令就編譯進去,一般用預設的就可以了,配置好後退出並儲存。 
  4、編譯並安裝busybox 
  #make 
  #make install 
  編譯好後在busybox目錄下生成子目錄_install,裡面的內容: 
  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 
  其中可執行檔案busybox在bin目錄下,其他的都是指向他的符號連結. 

Android系統在超級終端下必會的命令大全(二) 

一、安裝和登入命令 
reboot 
1.作用 
reboot命令的作用是重新啟動計算機,它的使用許可權是系統管理者。 
2.格式 
reboot [-n] [-w] [-d] [-f] [-i] 
3.主要引數 
-n: 在重開機前不做將記憶體資料寫回硬碟的動作。 
-w: 並不會真的重開機,只是把記錄寫到/var/log/wtmp檔案裡。 
-d: 不把記錄寫到/var/log/wtmp檔案裡(-n這個引數包含了-d)。 
-i: 在重開機之前先把所有與網路相關的裝置停止。 
mount 
1.作用 
mount命令的作用是載入檔案系統,它的用許可權是超級使用者或/etc/fstab中允許的使用者。 
2.格式 
mount -a [-fv] [-t vfstype] [-n] [-rw] [-F] device dir 
3.主要引數 
-h:顯示輔助資訊。 
-v:顯示資訊,通常和-f用來除錯。 
-a:將/etc/fstab中定義的所有檔案系統掛上。 
-F:這個命令通常和-a一起使用,它會為每一個mount的動作產生一個行程負責執行。在系統需要掛上大量NFS檔案系統時可以加快載入的速度。 
-f:通常用於除錯。它會使mount不執行實際掛上的動作,而是模擬整個掛上的過程,通常會和-v一起使用。 
-t vfstype:顯示被載入檔案系統的型別。 
-n:一般而言,mount掛上後會在/etc/mtab中寫入一筆資料,在系統中沒有可寫入檔案系統的情況下,可以用這個選項取消這個動作。 
4.應用技巧 
在 Linux和Unix系統上,所有檔案都是作為一個大型樹(以/為根)的一部分訪問的。要訪問CD-ROM上的檔案,需要將CD-ROM裝置掛裝在檔案樹中的某個掛裝點。如果發行版安裝了自動掛裝包,那麼這個步驟可自動進行。在Linux中,如果要使用硬碟、光碟機等儲存裝置,就得先將它載入,當儲存裝置掛上了之後,就可以把它當成一個目錄來訪問。掛上一個裝置使用mount命令。在使用mount這個指令時,至少要先知道下列三種資訊:要載入物件的檔案系統型別、要載入物件的裝置名稱及要將裝置載入到哪個目錄下。 
(1)Linux可以識別的檔案系統 
◆ Windows 95/98常用的FAT 32檔案系統:vfat ; 
◆ Win NT/2000 的檔案系統:ntfs ; 
◆ OS/2用的檔案系統:hpfs; 
◆ Linux用的檔案系統:ext2、ext3; 
◆ CD-ROM光碟用的檔案系統:iso9660。 
雖然vfat是指FAT 32系統,但事實上它也相容FAT 16的檔案系統型別。 
(2)確定裝置的名稱 
在Linux中,裝置名稱通常都存在/dev裡。這些裝置名稱的命名都是有規則的,可以用“推理”的方式把裝置名稱找出來。例如,/dev/hda1這個 
IDE裝置,hd是Hard Disk(硬碟)的,sd是SCSI Device,fd是Floppy Device(或是Floppy 
Disk?)。a代表第一個裝置,通常IDE介面可以接上4個IDE裝置(比如4塊硬碟)。所以要識別IDE硬碟的方法分別就是hda、hdb、hdc、 
hdd。hda1中的“1”代表hda的第一個硬碟分割槽 
(partition),hda2代表hda的第二主分割槽,第一個邏輯分割槽從hda5開始,依此類推。此外,可以直接檢查/var/log/messages檔案,在該檔案中可以找到計算機開機後系統已辨認出來的裝置代號。 
(3)查詢掛接點 
在決定將裝置掛接之前,先要檢視一下計算機是不是有個/mnt的空目錄,該目錄就是專門用來當作掛載點(MountPoint)的目錄。建議在/mnt裡建幾個/mnt/cdrom、/mnt/floppy、/mnt/mo等目錄,當作目錄的專用掛載點。舉例而言,如要掛載下列5個裝置,其執行指令可能如下 (假設都是Linux的ext2系統,如果是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 
不過目前大多數較新的Linux發行版本(包括紅旗 Linux、中軟Linux、Mandrake Linux等)都可以自動掛裝檔案系統,但Red Hat Linux除外。 
umount 
1.作用 
umount命令的作用是解除安裝一個檔案系統,它的使用許可權是超級使用者或/etc/fstab中允許的使用者。 
2.格式 
unmount -a [-fFnrsvw] [-t vfstype] [-n] [-rw] [-F] device dir 
3.使用說明 
umount 
命令是mount命令的逆操作,它的引數和使用方法和mount命令是一樣的。Linux掛裝CD-ROM後,會鎖定CD—ROM,這樣就不能用CD- 
ROM皮膚上的Eject按鈕彈出它。但是,當不再需要光碟時,如果已將/cdrom作為符號連結,請使用umount/cdrom來卸裝它。僅當無使用者 
正在使用光碟時,該命令才會成功。該命令包括了將帶有當前工作目錄當作該光碟中的目錄的終端視窗。 
exit 
1.作用 
exit命令的作用是退出系統,它的使用許可權是所有使用者。 
2.格式 
exit 
3.引數 
exit命令沒有引數,執行後退出系統進入登入介面。 




-------------------------------------------------------------------------------- 
作者: ☆-☆    時間: 2010-6-8 11:52 

Android系統在超級終端下必會的命令大全(三) 
二、檔案處理命令 
mkdir 
1.作用 
mkdir命令的作用是建立名稱為dirname的子目錄,與MS DOS下的md命令類似,它的使用許可權是所有使用者。 
2.格式 
mkdir [options] 目錄名 
3.[options]主要引數 
-m, --mode=模式:設定許可權,與chmod類似。 
-p, --parents:需要時建立上層目錄;如果目錄早已存在,則不當作錯誤。 
-v, --verbose:每次建立新目錄都顯示資訊。 
--version:顯示版本資訊後離開。 
4.應用例項 
在進行目錄建立時可以設定目錄的許可權,此時使用的引數是“-m”。假設要建立的目錄名是“tsk”,讓所有使用者都有rwx(即讀、寫、執行的許可權),那麼可以使用以下命令: 
$ mkdir -m 777 tsk 
grep 
1.作用 
grep命令可以指定檔案中搜尋特定的內容,並將含有這些內容的行標準輸出。grep全稱是Global Regular Expression Print,表示全域性正規表示式版本,它的使用許可權是所有使用者。 
2.格式 
grep [options] 
3.主要引數 
[options]主要引數: 
-c:只輸出匹配行的計數。 
-I:不區分大小寫(只適用於單字元)。 
-h:查詢多檔案時不顯示檔名。 
-l:查詢多檔案時只輸出包含匹配字元的檔名。 
-n:顯示匹配行及行號。 
-s:不顯示不存在或無匹配文字的錯誤資訊。 
-v:顯示不包含匹配文字的所有行。 
pattern正規表示式主要引數: 
\:忽略正規表示式中特殊字元的原有含義。 
^:匹配正規表示式的開始行。 
$: 匹配正規表示式的結束行。 
\:到匹配正規表示式的行結束。 
[ ]:單個字元,如[A]即A符合要求 。 
[ - ]:範圍,如[A-Z],即A、B、C一直到Z都符合要求 。 
。:所有的單個字元。 
* :有字元,長度可以為0。 
正規表示式是Linux/Unix系統中非常重要的概念。正規表示式(也稱為“regex”或“regexp”)是一個可以描述一類字串的模式(Pattern)。如果一個字串可以用某個正規表示式來描述,我們就說這個字元和該正規表示式匹配(Match)。這和DOS中使用者可以使用萬用字元 
“*”代表任意字元類似。在Linux系統上,正規表示式通常被用來查詢文字的模式,以及對文字執行“搜尋-替換”操作和其它功能。 
4.應用例項 
查詢DNS服務是日常工作之一,這意味著要維護覆蓋不同網路的大量IP地址。有時IP地址會超過2000個。如果要檢視nnn.nnn網路地址,但是卻忘了第二部分中的其餘部分,只知到有兩個句點,例如nnn nn..。要抽取其中所有nnn.nnn IP地址,使用[09 ]\{3 
\}\.[00\{3\}\。含義是任意數字出現3次,後跟句點,接著是任意數字出現3次,後跟句點。 
$grep ’[09 ]\{3 \}\.[00\{3\}\’ ipfile 
補充說明,grep家族還包括fgrep和egrep。fgrep是fix grep,允許查詢字串而不是一個模式;egrep是擴充套件grep,支援基本及擴充套件的正規表示式,但不支援\q模式範圍的應用及與之相對應的一些更加規範的模式。 
dd 
1.作用 
dd命令用來複制檔案,並根據引數將資料轉換和格式化。 
2.格式 
dd [options] 
3.[opitions]主要引數 
bs=位元組:強迫 ibs=及obs=。 
cbs=位元組:每次轉換指定的。 
conv=關鍵字:根據以逗號分隔的關鍵字表示的方式來轉換檔案。 
count=塊數目:只複製指定的輸入資料。 
ibs=位元組:每次讀取指定的。 
if=檔案:讀取內容,而非標準輸入的資料。 
obs=位元組:每次寫入指定的。 
of=檔案:將資料寫入,而不在標準輸出顯示。 
seek=塊數目:先略過以obs為單位的指定的輸出資料。 
skip=塊數目:先略過以ibs為單位的指定的輸入資料。 
4.應用例項 
dd命令常常用來製作Linux啟動盤。先找一個可引導核心,令它的根裝置指向正確的根分割槽,然後使用dd命令將其寫入軟盤: 
$ rdev vmlinuz /dev/hda 
$dd if=vmlinuz of=/dev/fd0 
上面程式碼說明,使用rdev命令將可引導核心vmlinuz中的根裝置指向/dev/hda,請把“hda”換成自己的根分割槽,接下來用dd命令將該核心寫入軟盤。 



find 
1.作用 
find命令的作用是在目錄中搜尋檔案,它的使用許可權是所有使用者。 
2.格式 
find [path][options][expression] 
path指定目錄路徑,系統從這裡開始沿著目錄樹向下查詢檔案。它是一個路徑列表,相互用空格分離,如果不寫path,那麼預設為當前目錄。 
3.主要引數 
[options]引數: 
-depth:使用深度級別的查詢過程方式,在某層指定目錄中優先查詢檔案內容。 
-maxdepth levels:表示至多查詢到開始目錄的第level層子目錄。level是一個非負數,如果level是0的話表示僅在當前目錄中查詢。 
-mindepth levels:表示至少查詢到開始目錄的第level層子目錄。 
-mount:不在其它檔案系統(如Msdos、Vfat等)的目錄和檔案中查詢。 
-version:列印版本。 
[expression]是匹配表示式,是find命令接受的表示式,find命令的所有操作都是針對表示式的。它的引數非常多,這裡只介紹一些常用的引數。 
—name:支援統配符*和?。 
-atime n:搜尋在過去n天讀取過的檔案。 
-ctime n:搜尋在過去n天修改過的檔案。 
-group grpoupname:搜尋所有組為grpoupname的檔案。 
-user 使用者名稱:搜尋所有檔案屬主為使用者名稱(ID或名稱)的檔案。 
-size n:搜尋檔案大小是n個block的檔案。 
-print:輸出搜尋結果,並且列印。 
4.應用技巧 
find命令查詢檔案的幾種方法: 
(1)根據檔名查詢 
例如,我們想要查詢一個檔名是lilo.conf的檔案,可以使用如下命令: 
find / -name lilo.conf 
find命令後的“/”表示搜尋整個硬碟。 
(2)快速查詢檔案 
根據檔名查詢檔案會遇到一個實際問題,就是要花費相當長的一段時間,特別是大型Linux檔案系統和大容量硬碟檔案放在很深的子目錄中時。如果我們知道了這個檔案存放在某個目錄中,那麼只要在這個目錄中往下尋找就能節省很多時間。比如smb.conf檔案,從它的檔案字尾“.conf”可以判斷這是一個配置檔案,那麼它應該在/etc目錄內,此時可以使用下面命令: 
find /etc -name smb.conf 
這樣,使用“快速查詢檔案”方式可以縮短時間。 
(3)根據部分檔名查詢方法 
有時我們知道只某個檔案包含有abvd這4個字,那麼要查詢系統中所有包含有這4個字元的檔案可以輸入下面命令: 
find / -name ’*abvd*’ 
輸入這個命令以後,Linux系統會將在/目錄中查詢所有的包含有abvd這4個字元的檔案(其中*是萬用字元),比如abvdrmyz等符合條件的檔案都能顯示出來。 
(4) 使用混合查詢方式查詢檔案 
find命令可以使用混合查詢的方法,例如,我們想在/etc目錄中查詢大於500000位元組,並且在24小時內修改的某個檔案,則可以使用-and (與)把兩個查詢引數連結起來組合成一個混合的查詢方式。 
find /etc -size +500000c -and -mtime +1 
mv 
1.作用 
mv命令用來為檔案或目錄改名,或者將檔案由一個目錄移入另一個目錄中,它的使用許可權是所有使用者。該命令如同DOS命令中的ren和move的組合。 
2.格式 
mv[options] 原始檔或目錄 目標檔案或目錄 
3.[options]主要引數 
-i:互動方式操作。如果mv操作將導致對已存在的目標檔案的覆蓋,此時系統詢問是否重寫,要求使用者回答“y”或“n”,這樣可以避免誤覆蓋檔案。 
-f:禁止互動操作。mv操作要覆蓋某個已有的目標檔案時不給任何指示,指定此引數後i引數將不再起作用。 
4.應用例項 
(1)將/usr/cbu中的所有檔案移到當前目錄(用“.”表示)中: 
$ mv /usr/cbu/ * . 
(2)將檔案cjh.txt重新命名為wjz.txt: 
$ mv cjh.txt wjz.txt  
ls 
1.作用 
ls命令用於顯示目錄內容,類似DOS下的dir命令,它的使用許可權是所有使用者。 
2.格式 
ls [options][filename] 
3.options主要引數 
-a, --all:不隱藏任何以“.” 字元開始的專案。 
-A, --almost-all:列出除了“ . ”及 “.. ”以外的任何專案。 
--author:印出每個檔案著作者。 
-b, --escape:以八進位制溢位序列表示不可列印的字元。 
--block-size=大小:塊以指定的位元組為單位。 
-B, --ignore-backups:不列出任何以 ~ 字元結束的專案。 
-f:不進行排序,-aU引數生效,-lst引數失效。 
-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:當顯示符號連結的檔案資訊時,顯示符號連結所指示的物件,而並非符號連結本身的資訊。 
-m:所有專案以逗號分隔,並填滿整行行寬。 
-n, --numeric-uid-gid:類似-l,但列出UID及GID號。 
-N, --literal:列出未經處理的專案名稱,例如不特別處理控制字元。 
-p, --file-type:加上檔案型別的指示符號 (/=@| 其中一個)。 
-Q, --quote-name:將專案名稱括上雙引號。 
-r, --reverse:依相反次序排列。 
-R, --recursive:同時列出所有子目錄層。 
-s, --size:以塊大小為序。 
4.應用舉例 
ls 
命令是Linux系統使用頻率最多的命令,它的引數也是Linux命令中最多的。使用ls命令時會有幾種不同的顏色,其中藍色表示是目錄,綠色表示是可執 
行檔案,紅色表示是壓縮檔案,淺藍色表示是連結檔案,加粗的黑色表示符號連結,灰色表示是其它格式檔案。ls最常使用的是ls- l。 
文 
件型別開頭是由10個字元構成的字串。其中第一個字元表示檔案型別,它可以是下述型別之一:-(普通檔案)、d(目錄)、l(符號連結)、b(塊裝置檔案)、c(字元裝置檔案)。後面的9個字元表示檔案的訪問許可權,分為3組,每組3位。第一組表示檔案屬主的許可權,第二組表示同組使用者的許可權,第三組表示其他使用者的許可權。每一組的三個字元分別表示對檔案的讀(r)、寫(w)和執行許可權(x)。對於目錄,表示進入許可權。s表示當檔案被執行時,把該檔案的UID 或GID賦予執行程式的UID(使用者ID)或GID(組ID)。t表示設定標誌位(留在記憶體,不被換出)。如果該檔案是目錄,那麼在該目錄中的檔案只能被超級使用者、目錄擁有者或檔案屬主刪除。如果它是可執行檔案,那麼在該檔案執行後,指向其正文段的指標仍留在記憶體。這樣再次執行它時,系統就能更快地裝入該檔案。接著顯示的是檔案大小、生成時間、檔案或命令名稱。 
Android系統在超級終端下必會的命令大全(四) 
diff 
1.作用 
diff命令用於兩個檔案之間的比較,並指出兩者的不同,它的使用許可權是所有使用者。 
2.格式 
diff [options] 原始檔 目標檔案 
3.[options]主要引數 
-a:將所有檔案當作文字檔案來處理。 
-b:忽略空格造成的不同。 
-B:忽略空行造成的不同。 
-c:使用綱要輸出格式。 
-H:利用試探法加速對大檔案的搜尋。 
-I:忽略大小寫的變化。 
-n --rcs:輸出RCS格式。 
cmp 
1.作用 
cmp(“compare”的縮寫)命令用來簡要指出兩個檔案是否存在差異,它的使用許可權是所有使用者。 
2.格式 
cmp[options] 檔名 
3.[options]主要引數 
-l: 將位元組以十進位制的方式輸出,並方便將兩個檔案中不同的以八進位制的方式輸出。 
cat 
1.作用 
cat(“concatenate”的縮寫)命令用於連線並顯示指定的一個和多個檔案的有關資訊,它的使用許可權是所有使用者。 
2.格式 
cat [options] 檔案1 檔案2…… 
3.[options]主要引數 
-n:由第一行開始對所有輸出的行數編號。 
-b:和-n相似,只不過對於空白行不編號。 
-s:當遇到有連續兩行以上的空白行時,就代換為一行的空白行。 
4.應用舉例 
(1)cat命令一個最簡單的用處是顯示文字檔案的內容。例如,我們想在命令列看一下README檔案的內容,可以使用命令: 
$ cat README  
(2)有時需要將幾個檔案處理成一個檔案,並將這種處理的結果儲存到一個單獨的輸出檔案。cat命令在其輸入上接受一個或多個檔案,並將它們作為一個單獨的檔案列印到它的輸出。例如,把README和INSTALL的檔案內容加上行號(空白行不加)之後,將內容附加到一個新文字檔案File1 中: 
$ cat README INSTALL File1 
(3)cat 還有一個重要的功能就是可以對行進行編號。這種功能對於程式文件的編制,以及法律和科學文件的編制很方便,列印在左邊的行號使得參考文件的某一部分變得容易,這些在程式設計、科學研究、業務報告甚至是立法工作中都是非常重要的。對行進行編號功能有-b(只能對非空白行進行編號)和-n(可以對所有行進行編號)兩個引數: 
$ cat -b /etc/named.conf 
ln 
1.作用 
ln命令用來在檔案之間建立連結,它的使用許可權是所有使用者。 
2.格式 
ln [options] 原始檔 [連結名] 
3.引數 
-f:鏈結時先將原始檔刪除。 
-d:允許系統管理者硬鏈結自己的目錄。 
-s:進行軟鏈結(Symbolic Link)。 
-b:將在鏈結時會被覆蓋或刪除的檔案進行備份。 
連結有兩種,一種被稱為硬連結(Hard Link),另一種被稱為符號連結(Symbolic Link)。預設情況下,ln命令產生硬連結。硬連線指通過索引節點來進行的連線。在Linux的檔案系統中,儲存在磁碟分割槽中的檔案不管是什麼型別都給它分配一個編號,稱為索引節點號(InodeIndex)。在Linux中,多個檔名指向同一索引節點是存在的。一般這種連線就是硬連線。硬連線的作用是允許一個檔案擁有多個有效路徑名,這樣使用者就可以建立硬連線到重要檔案,以防止“誤刪”的功能。其原因如上所述,因為對應該目錄的索引節點有一個以上的連線。只刪除一個連線並不影響索引節點本身和其它的連線,只有當最後一個連線被刪除後,檔案的資料塊及目錄的連線才會被釋放。也就是說,檔案才會被真正刪除。與硬連線相對應,Lnux系統中還存在另一種連線,稱為符號連線(Symbilc Link),也叫軟連線。軟連結檔案有點類似於Windows的快捷方式。它實際上是特殊檔案的一種。在符號連線中,檔案實際上是一個文字檔案,其中包含的有另一檔案的位置資訊。 
-------------------------------------------------------------------------------- 
作者: ☆-☆    時間: 2010-6-8 11:55 

本帖最後由 ☆-☆ 於 2010-6-8 11:59 編輯 

Android系統在超級終端下必會的命令大全(五) 
系統管理命令 
df 
1.作用 
df命令用來檢查檔案系統的磁碟空間佔用情況,使用許可權是所有使用者。 
2.格式 
df [options] 
3.主要引數 
-s:對每個Names引數只給出佔用的資料塊總數。 
-a:遞迴地顯示指定目錄中各檔案及子目錄中各檔案佔用的資料塊數。若既不指定-s,也不指定-a,則只顯示Names中的每一個目錄及其中的各子目錄所佔的磁碟塊數。 
-k:以1024位元組為單位列出磁碟空間使用情況。 
-x:跳過在不同檔案系統上的目錄不予統計。 
-l:計算所有的檔案大小,對硬連結檔案則計算多次。 
-i:顯示inode資訊而非塊使用量。 
-h:以容易理解的格式印出檔案系統大小,例如136KB、254MB、21GB。 
-P:使用POSIX輸出格式。 
-T:顯示檔案系統型別。 
4.說明 
df 命令被廣泛地用來生成檔案系統的使用統計資料,它能顯示系統中所有的檔案系統的資訊,包括總容量、可用的空閒空間、目前的安裝點等。超級許可權使用者使用df 命令時會發現這樣的情況:某個分割槽的容量超過了100%。這是因為Linux系統為超級使用者保留了10%的空間,由其單獨支配。也就是說,對於超級使用者而言,他所見到的硬碟容量將是110%。這樣的安排對於系統管理而言是有好處的,當硬碟被使用的容量接近100%時系統管理員還可以正常工作。 
5.應用例項 
Linux支援的檔案系統非常多,包括JFS、ReiserFS、ext、ext2、ext3、ISO9660、XFS、Minx、vfat、MSDOS等。使用df -T命令檢視磁碟空間時還可以得到檔案系統的資訊: 
#df -T 
檔案系統 型別 容量 已用 可用 已用% 掛載點 
/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 
從上面除了可以看到磁碟空間的容量、使用情況外,分割槽的檔案系統型別、掛載點等資訊也一覽無遺。 
top 
1.作用 
top命令用來顯示執行中的程式程式,使用許可權是所有使用者。 
2.格式 
top [-] [d delay] [q] [c] [S] [n] 
3.主要引數 
d:指定更新的間隔,以秒計算。 
q:沒有任何延遲的更新。如果使用者有超級使用者,則top命令將會以最高的優先序執行。 
c:顯示程式完整的路徑與名稱。 
S:累積模式,會將己完成或消失的子行程的CPU時間累積起來。 
s:安全模式。 
i:不顯示任何閒置(Idle)或無用(Zombie)的行程。 
n:顯示更新的次數,完成後將會退出top。 
4.說明 
top命令是Linux系統管理的一個主要命令,通過它可以獲得許多資訊。 
下面列出了詳細解釋。 
PID(Process ID):程式標示號。 
USER:程式所有者的使用者名稱。 
PR:程式的優先順序別。 
NI:程式的優先順序別數值。 
VIRT:程式佔用的虛擬記憶體值。 
RES:程式佔用的實體記憶體值。 
SHR:程式使用的共享記憶體值。 
S:程式的狀態,其中S表示休眠,R表示正在執行,Z表示僵死狀態,N表示該程式優先值是負數。 
%CPU:該程式佔用的CPU使用率。 
%MEM:該程式佔用的實體記憶體和總記憶體的百分比。 
TIME+:該程式啟動後佔用的總的CPU時間。 
Command:程式啟動的啟動命令名稱,如果這一行顯示不下,程式會有一個完整的命令列。 
top命令使用過程中,還可以使用一些互動的命令來完成其它引數的功能。這些命令是通過快捷鍵啟動的。 
:立刻重新整理。 
P:根據CPU使用大小進行排序。 
T:根據時間、累計時間排序。 
q:退出top命令。 
m:切換顯示記憶體資訊。 
t:切換顯示程式和CPU狀態資訊。 
c:切換顯示命令名稱和完整命令列。 
M:根據使用記憶體大小進行排序。 
W:將當前設定寫入~/.toprc檔案中。這是寫top配置檔案的推薦方法。 
可以看到,top命令是一個功能十分強大的監控系統的工具,對於系統管理員而言尤其重要。但是,它的缺點是會消耗很多系統資源。 


free 
1.作用 
free命令用來顯示記憶體的使用情況,使用許可權是所有使用者。 
2.格式 
free [-b|-k|-m] [-o] [-s delay] [-t] [-V] 
3.主要引數 
-b -k -m:分別以位元組(KB、MB)為單位顯示記憶體使用情況。 
-s delay:顯示每隔多少秒數來顯示一次記憶體使用情況。 
-t:顯示記憶體總和列。 
-o:不顯示緩衝區調節列。 
4.應用例項 
free命令是用來檢視記憶體使用情況的主要命令。和top命令相比,它的優點是使用簡單,並且只佔用很少的系統資源。通過-S引數可以使用free命令不間斷地監視有多少記憶體在使用,這樣可以把它當作一個方便實時監控器。 
#free -b -s5 
使用這個命令後終端會連續不斷地報告記憶體使用情況(以位元組為單位),每5秒更新一次。 

chown 
1.作用 
更改一個或多個檔案或目錄的屬主和屬組。使用許可權是超級使用者。 
2.格式 
chown [選項] 使用者或組 檔案 
3.主要引數 
--dereference:受影響的是符號連結所指示的物件,而非符號連結本身。 
-h, --no-dereference:會影響符號連結本身,而非符號連結所指示的目的地(當系統支援更改符號連結的所有者,此選項才有效)。 
--from=目前所有者:目前組只當每個檔案的所有者和組符合選項所指定的,才會更改所有者和組。其中一個可以省略,這已省略的屬性就不需要符合原有的屬性。 
-f, --silent, --quiet:去除大部分的錯誤資訊。 
-R, --recursive:遞迴處理所有的檔案及子目錄。 
-v, --verbose:處理任何檔案都會顯示資訊。 
4.說明 
chown 將指定檔案的擁有者改為指定的使用者或組,使用者可以是使用者名稱或使用者ID;組可以是組名或組ID;檔案是以空格分開的要改變許可權的檔案列表,支援萬用字元。系統管理員經常使用chown命令,在將檔案拷貝到另一個使用者的目錄下以後,讓使用者擁有使用該檔案的許可權。 
5.應用例項 
1.把檔案shiyan.c的所有者改為wan 
$ chown wan shiyan.c 
2.把目錄/hi及其下的所有檔案和子目錄的屬主改成wan,屬組改成users。 
$ chown - R wan.users /hi 
chattr 
1.作用 
修改ext2和ext3檔案系統屬性(attribute),使用許可權超級使用者。 
2.格式 
chattr [-RV] [-+=AacDdijsSu] [-v version] 檔案或目錄 
3.主要引數 
-R:遞迴處理所有的檔案及子目錄。 
-V:詳細顯示修改內容,並列印輸出。 
-:失效屬性。 
+:啟用屬性。 
= :指定屬性。 
A:Atime,告訴系統不要修改對這個檔案的最後訪問時間。 
S:Sync,一旦應用程式對這個檔案執行了寫操作,使系統立刻把修改的結果寫到磁碟。 
a:Append Only,系統只允許在這個檔案之後追加資料,不允許任何程式覆蓋或截斷這個檔案。如果目錄具有這個屬性,系統將只允許在這個目錄下建立和修改檔案,而不允許刪除任何檔案。 
i:Immutable,系統不允許對這個檔案進行任何的修改。如果目錄具有這個屬性,那麼任何的程式只能修改目錄之下的檔案,不允許建立和刪除檔案。 
D:檢查壓縮檔案中的錯誤。 
d:No dump,在進行檔案系統備份時,dump程式將忽略這個檔案。 
C:Compress,系統以透明的方式壓縮這個檔案。從這個檔案讀取時,返回的是解壓之後的資料;而向這個檔案中寫入資料時,資料首先被壓縮之後才寫入磁碟。 
s:Secure Delete,讓系統在刪除這個檔案時,使用0填充檔案所在的區域。 
u:Undelete,當一個應用程式請求刪除這個檔案,系統會保留其資料塊以便以後能夠恢復刪除這個檔案。 
4.說明 
chattr 
命令的作用很大,其中一些功能是由Linux核心版本來支援的,如果Linux核心版本低於2.2,那麼許多功能不能實現。同樣-D檢查壓縮檔案中的錯誤 
的功能,需要2.5.19以上核心才能支援。另外,通過chattr命令修改屬效能夠提高系統的安全性,但是它並不適合所有的目錄。chattr命令不能 
保護/、/dev、/tmp、/var目錄。 
5.應用例項 
1.恢復/root目錄,即子目錄的所有檔案 
# chattr -R +u/root 
2.用chattr命令防止系統中某個關鍵檔案被修改 
在Linux下,有些配置檔案(passwd ,fatab)是不允許任何人修改的,為了防止被誤刪除或修改,可以設定該檔案的“不可修改位(immutable)”,命令如下: 
# chattr +i /etc/fstab 
ps 
1.作用 
ps顯示瞬間程式 (process) 的動態,使用許可權是所有使用者。 
2.格式 
ps [options] [--help] 
3.主要引數 
ps的引數非常多, 此出僅列出幾個常用的引數。 
-A:列出所有的程式。 
-l:顯示長列表。 
-m:顯示記憶體資訊。 
-w:顯示加寬可以顯示較多的資訊。 
-e:顯示所有程式。 
a:顯示終端上的所有程式,包括其它使用者的程式。 
-au:顯示較詳細的資訊。 
-aux:顯示所有包含其它使用者的程式。 
4.說明 
要 
對程式進行監測和控制,首先要了解當前程式的情況,也就是需要檢視當前程式。ps命令就是最基本、也是非常強大的程式檢視命令。使用該命令可以確定有哪些 
程式正在執行、執行的狀態、程式是否結束、程式有沒有殭屍、哪些程式佔用了過多的資源等。圖2給出了ps-aux命令詳解。大部分資訊都可以通過執行該命 
令得到。最常用的三個引數是u、a、x。下面就結合這三個引數詳細說明ps命令的作用:ps aux 
圖2 ps-aux命令詳解 
圖2第2行程式碼中,USER表示程式擁有者;PID表示程式標示符;%CPU表示佔用的CPU使用率;%MEM佔用的實體記憶體使用率;VSZ表示佔用的虛擬記憶體大小;RSS為程式佔用的實體記憶體值;TTY為終端的次要裝置號碼。 
STAT 
表示程式的狀態,其中D為不可中斷的靜止(I/O動作);R正在執行中;S靜止狀態;T暫停執行;Z不存在,但暫時無法消除;W沒有足夠的記憶體分頁可分 
配;高優先序的程式;N低優先序的程式;L有記憶體分頁分配並鎖在記憶體體內 (實時系統或 
I/O)。START為程式開始時間。TIME為執行的時間。COMMAND是所執行的指令。 
4.應用例項 
在進行系統維護時,經常會出現記憶體使用量驚人,而又不知道是哪一個程式佔用了大量程式的情況。除了可以使用top命令檢視記憶體使用情況之外,還可以使用下面的命令: 
ps aux | sort +5n 
-------------------------------------------------------------------------------- 
作者: ☆-☆    時間: 2010-6-8 11:58 

Android系統在超級終端下必會的命令大全(十) 
六、其他命令 
tar 
1.作用 
tar命令是Unix/Linux系統中備份檔案的可靠方法,幾乎可以工作於任何環境中,它的使用許可權是所有使用者。 
2.格式 
tar [主選項+輔選項] 檔案或目錄 
3.主要引數 
使用該命令時,主選項是必須要有的,它告訴tar要做什麼事情,輔選項是輔助使用的,可以選用。 
主選項: 
-c 建立新的檔案檔案。如果使用者想備份一個目錄或是一些檔案,就要選擇這個選項。 
-r 把要存檔的檔案追加到檔案檔案的未尾。例如使用者已經做好備份檔案,又發現還有一個目錄或是一些檔案忘記備份了,這時可以使用該選項,將忘記的目錄或檔案追加到備份檔案中。 
-t 列出檔案檔案的內容,檢視已經備份了哪些檔案。 
-u 更新檔案。就是說,用新增的檔案取代原備份檔案,如果在備份檔案中找不到要更新的檔案,則把它追加到備份檔案的最後。 
-x 從檔案檔案中釋放檔案。 
輔助選項: 
-b 該選項是為磁帶機設定的,其後跟一數字,用來說明區塊的大小,系統預設值為20(20×512 bytes)。 
-f 使用檔案檔案或裝置,這個選項通常是必選的。 
-k 儲存已經存在的檔案。例如把某個檔案還原,在還原的過程中遇到相同的檔案,不會進行覆蓋。 
-m 在還原檔案時,把所有檔案的修改時間設定為現在。 
-M 建立多卷的檔案檔案,以便在幾個磁碟中存放。 
-v 詳細報告tar處理的檔案資訊。如無此選項,tar不報告檔案資訊。 
-w 每一步都要求確認。 
-z 用gzip來壓縮/解壓縮檔案,加上該選項後可以將檔案檔案進行壓縮,但還原時也一定要使用該選項進行解壓縮。 
4.應用說明 
tar 是Tape Archive(磁帶歸檔)的縮寫,最初設計用於將檔案打包到磁帶上。如果下載過Linux的原始碼,或許已經碰到過tar檔案 
請注意,不要忘了Linux是區分大小寫的。例如,tar命令應該總是以小寫的形式執行。命令列開關可以是大寫、小寫或大小寫的混合。例如,-t和-T執行不同的功能。檔案或目錄名稱可以混合使用大小寫,而且就像命令和命令列開關一樣是區分大小寫的。 
5.應用例項 
tar是一個命令列的工具,沒有圖形介面。使用Konsole開啟一個終端視窗,接下來是一個簡單的備份命令(在/temp目錄中建立一個back.tar的檔案,/usr目錄中所有內容都包含在其中。): 
$tar cvf - /usr > /temp/back.tar 
另 
外,tar命令支援前面第三講中講過的crontab命令,可以用crontab工具設定成基於時間的有規律地執行。例如,每晚6點把/usr目錄備份到 
hda—第一個IDE介面的主驅動器 (總是位於第一個硬碟)中,只要將下面語句新增到root的crontab中即可: 
$00 06 * * * tar cvf /dev/hda1/usrfiles.tar - /usr 
一般情況下,以下這些目錄是需要備份的: 
◆/etc 包含所有核心配置檔案,其中包括網路配置、系統名稱、防火牆規則、使用者、組,以及其它全域性系統項。 
◆ /var 包含系統守護程式(服務)所使用的資訊,包括DNS配置、DHCP租期、郵件緩衝檔案、HTTP伺服器檔案、dB2例項配置等。 
◆/home 包含所有預設使用者的主目錄,包括個人設定、已下載的檔案和使用者不希望失去的其它資訊。 
◆/root 根(root)使用者的主目錄。 
◆/opt 是安裝許多非系統檔案的地方。IBM軟體就安裝在這裡。OpenOffice、JDK和其它軟體在預設情況下也安裝在這裡。 
有些目錄是可以不備份的: 
◆ /proc 應該永遠不要備份這個目錄。它不是一個真實的檔案系統,而是執行核心和環境的虛擬化檢視,包括諸如/proc/kcore這樣的檔案,這個檔案是整個執行記憶體的虛擬檢視。備份這些檔案只是在浪費資源。 
◆/dev 包含硬體裝置的檔案表示。如果計劃還原到一個空白的系統,就可以備份/dev。然而,如果計劃還原到一個已安裝的Linux 系統,那麼備份/dev是沒有必要的。 
unzip 
1.作用 
unzip 
命令位於/usr/bin目錄中,它們和MS DOS下的pkzip、pkunzip及MS 
Windows中的Winzip軟體功能一樣,將檔案壓縮成.zip檔案,以節省硬碟空間,當需要的時候再將壓縮檔案用unzip命令解開。該命令使用權 
限是所有使用者。 
2.格式 
unzip [-cflptuvz][-agCjLMnoqsVX][-P ][.zip檔案][檔案][-d ][-x ] 
3.主要引數 
-c:將解壓縮的結果顯示到螢幕上,並對字元做適當的轉換。 
-f:更新現有的檔案。 
-l:顯示壓縮檔案內所包含的檔案。 
-p:與-c引數類似,會將解壓縮的結果顯示到螢幕上,但不會執行任何的轉換。 
-t:檢查壓縮檔案是否正確。 
-u:與-f引數類似,但是除了更新現有的檔案外,也會將壓縮檔案中的其它檔案解壓縮到目錄中。 
-v:執行是時顯示詳細的資訊。 
-z:僅顯示壓縮檔案的備註文字。 
-a:對文字檔案進行必要的字元轉換。 
-b:不要對文字檔案進行字元轉換。 
-C:壓縮檔案中的檔名稱區分大小寫。 
-j:不處理壓縮檔案中原有的目錄路徑。 
-L:將壓縮檔案中的全部檔名改為小寫。 
-M:將輸出結果送到more程式處理。 
-n:解壓縮時不要覆蓋原有的檔案。 
-o:不必先詢問使用者,unzip執行後覆蓋原有檔案。 
-P:使用zip的密碼選項。 
-q:執行時不顯示任何資訊。 
-s:將檔名中的空白字元轉換為底線字元。 
-V:保留VMS的檔案版本資訊。 
-X:解壓縮時同時回存檔案原來的UID/GID。 
[.zip檔案]:指定.zip壓縮檔案。 
[檔案]:指定要處理.zip壓縮檔案中的哪些檔案。 
-d:指定檔案解壓縮後所要儲存的目錄。 
-x:指定不要處理.zip壓縮檔案中的哪些檔案。 
-Z unzip:-Z等於執行zipinfo指令。在Linux中,還提供了一個叫zipinfo的工具,能夠察看zip壓縮檔案的詳細資訊。 
gunzip 
1.作用 
gunzip命令作用是解壓檔案,使用許可權是所有使用者。 
2.格式 
gunzip [-acfhlLnNqrtvV][-s ][檔案...] 
或者 
gunzip [-acfhlLnNqrtvV][-s ][目錄] 
3.主要引數 
-a或--ascii:使用ASCII文字模式。 
-c或--stdout或--to-stdout:把解壓後的檔案輸出到標準輸出裝置。 
-f或-force:強行解開壓縮檔案,不理會檔名稱或硬連線是否存在,以及該檔案是否為符號連線。 
-h或--help:線上幫助。 
-l或--list:列出壓縮檔案的相關資訊。 
-L或--license:顯示版本與版權資訊。 
-n或--no-name:解壓縮時,若壓縮檔案內含有原來的檔名稱及時間戳記,則將其忽略不予處理。 
-N或--name:解壓縮時,若壓縮檔案內含有原來的檔名稱及時間戳記,則將其回存到解開的檔案上。 
-q或--quiet:不顯示警告資訊。 
-r或--recursive:遞迴處理,將指定目錄下的所有檔案及子目錄一併處理。 
-S或--suffix:更改壓縮字尾字串。 
-t或--test:測試壓縮檔案是否正確無誤。 
-v或--verbose:顯示指令執行過程。 
-V或--version:顯示版本資訊。 
4.說明 
gunzip是個使用廣泛的解壓縮程式,它用於解開被gzip壓縮過的檔案,這些壓縮檔案預設最後的副檔名為“.gz”。事實上,gunzip就是gzip的硬連線,因此不論是壓縮或解壓縮,都可通過gzip指令單獨完成。gunzip最新版本是1.3.312:39
評論 / 瀏覽 (0 / 23)
分類:移動開發
2011-12-01
縮略顯示
java runtime.exec()相關
java


那就首先說點Runtime類吧,他是一個與JVM執行時環境有關的類,這個類是Singleton的。我說幾個自己覺得重要的地方。 

1、Runtime.getRuntime()可以取得當前JVM的執行時環境,這也是在Java中唯一一個得到執行時環境的方法。 

2、Runtime上其他大部分的方法都是例項方法,也就是說每次進行執行時呼叫時都要用到getRuntime方法。 

3、 Runtime中的exit方法是退出當前JVM的方法,估計也是唯一的一個吧,因為我看到System類中的exit實際上也是通過呼叫 Runtime.exit()來退出JVM的,這裡說明一下Java對Runtime返回值的一般規則(後邊也提到了),0代表正常退出,非0代表異常中止,這只是Java的規則,在各個作業系統中總會發生一些小的混淆。 

4、Runtime.addShutdownHook()方法可以註冊一個hook在JVM執行shutdown的過程中,方法的引數只要是一個初始化過但是沒有執行的Thread例項就可以。(注意,Java中的Thread都是執行過了就不值錢的哦) 

5、說到addShutdownHook這個方法就要說一下JVM執行環境是在什麼情況下shutdown或者abort的。文件上是這樣寫的,當最後一個非精靈程式退出或者收到了一個使用者中斷訊號、使用者登出、系統shutdown、Runtime的exit方法被呼叫時JVM會啟動shutdown的過程,在這個過程開始後,他會並行啟動所有登記的shutdown hook(注意是並行啟動,這就需要執行緒安全和防止死鎖)。當shutdown過程啟動後,只有通過呼叫halt方法才能中止shutdown的過程並退出JVM。 

那什麼時候JVM會abort退出那?首先說明一下,abort退出時JVM就是停止執行但並不一定進行shutdown。這隻有JVM在遇到SIGKILL訊號或者windows中止程式的訊號、本地方法發生類似於訪問非法地址一類的內部錯誤時會出現。這種情況下並不能保證shutdown hook是否被執行。 


現在開始看這篇文章,呵呵。 


首先講的是Runtime.exec()方法的所有過載。這裡要注意的有一點,就是public Process exec(String [] cmdArray, String [] envp);這個方法中cmdArray是一個執行的命令和引數的字串陣列,陣列的第一個元素是要執行的命令往後依次都是命令的引數,envp我個人感覺應該和C中的execve中的環境變數是一樣的,envp中使用的是name=value的方式。 


<!--[if !supportLists]-->1、 <!--[endif]-->一個很糟糕的呼叫程式,程式碼如下,這個程式用exec呼叫了一個外部命令之後馬上使用exitValue就對其返回值進行檢查,讓我們看看會出現什麼問題。 


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) 


這裡看原文就可以瞭解,這裡主要的問題就是錯誤的呼叫了exitValue來取得外部命令的返回值(呵呵,這個錯誤我也曾經犯過),因為exitValue 這個方法是不阻塞的,程式在呼叫這個方法時外部命令並沒有返回所以造成了異常的出現,這裡是由另外的方法來等待外部命令執行完畢的,就是waitFor方法,這個方法會一直阻塞直到外部命令執行結束,然後返回外部命令執行的結果,作者在這裡一頓批評設計者的思路有問題,呵呵,反正我是無所謂阿,能用就可以拉。但是作者在這裡有一個說明,就是exitValue也是有好多用途的。因為當你在一個Process上呼叫waitFor方法時,當前執行緒是阻塞的,如果外部命令無法執行結束,那麼你的執行緒就會一直阻塞下去,這種意外會影響我們程式的執行。所以在我們不能判斷外部命令什麼時候執行完畢而我們的程式還需要繼續執行的情況下,我們就應該迴圈的使用exitValue來取得外部命令的返回狀態,並在外部命令返回時作出相應的處理。 


2、對exitValue處改進了的程式 

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(); 
} 
} 
} 

不幸的是,這個程式也無法執行完成,它沒有輸出但卻一直懸在那裡,這是為什麼那? 


JDK文件中對此有如此的解釋:因為本地的系統對標準輸入和輸出所提供的緩衝池有效,所以錯誤的對標準輸出快速的寫入和從標準輸入快速的讀入都有可能造成子程式的鎖,甚至死鎖。 


文件引述完了,作者又開始批評了,他說JDK僅僅說明為什麼問題會發生,卻並沒有說明這個問題怎麼解決,這的確是個問題哈。緊接著作者說出自己的做法,就是在執行完外部命令後我們要控制好Process的所有輸入和輸出(視情況而定),在這個例子裡邊因為呼叫的是Javac,而他在沒有引數的情況下會將提示資訊輸出到標準出錯,所以在下面的程式中我們要對此進行處理。 


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(); 
} 
} 
} 


程式的執行結果為 

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 


哎,不管怎麼說還是出來了結果,作者作了一下總結,就是說,為了處理好外部命令大量輸出的情況,你要確保你的程式處理好外部命令所需要的輸入或者輸出。 


下一個題目,當我們呼叫一個我們認為是可執行程式的時候容易發生的錯誤(今天晚上我剛剛犯這個錯誤,沒事做這個練習時候發生的) 

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應該是沒有找到這個檔案的緣故,可能windows 2000中只有cmd命令,dir命令不是當前環境變數能夠解釋的吧。我也不知道了,慢慢往下看吧。 

嘿,果然和作者想的一樣,就是因為dir命令是由windows中的直譯器解釋的,直接執行dir時無法找到dir.exe這個命令,所以會出現檔案未找到這個2的錯誤。如果我們要執行這樣的命令,就要先根據作業系統的不同執行不同的解釋程式command.com 或者cmd.exe。 

作者對上邊的程式進行了修改 

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會自動地呼叫相關的程式來開啟這個文件,我試了一下,的確很好用,但是好像檔案路徑中有空格的話就有點問題,我加上引號也無法解決。 

這裡作者強調了一下,不要假設你執行的程式是可執行的程式,要清楚自己的程式是單獨可執行的還是被解釋的,本章的結束作者會介紹一個命令列工具來幫助我們分析。 

這裡還有一點,就是得到process的輸出的方式是getInputStream,這是因為我們要從Java 程式的角度來看,外部程式的輸出對於Java來說就是輸入,反之亦然。 


最後的一個漏洞的地方就是錯誤的認為exec方法會接受所有你在命令列或者Shell中輸入並接受的字串。這些錯誤主要出現在命令作為引數的情況下,程式設計師錯誤的將所有命令列中可以輸入的引數命令加入到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僅僅是將命令列中的引數輸出到標準輸出中,使用者覺得可以像dos中重定向一樣將輸出重定向到一個檔案中,但這並不能實現,使用者錯誤的將exec認為是一個shell直譯器,但它並不是,如果你想將一個程式的輸出重定向到其他的程式中,你必須用程式來實現他。可用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 

這裡就不多說了,看看就明白,緊接著作者給出了一個監測命令的小程式 

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(); 
} 
} 
} 

對這個程式進行執行: 
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程式,這說明路徑中找不到這個網頁的關聯程式,下面作者決定用一個絕對路徑來試一下。 

E:classescomjavaworldjpitfallsarticle2>java TestExec 
"e:program filesnetscapeprogramnetscape.exe e:javadocsindex.html" 
ExitValue: 0 


好用了,這個我也試了一下,用的是IE。 


最後,作者總結了幾條規則,防止我們在進行Runtime.exec()呼叫時出現錯誤。 


<!--[if !supportLists]-->1、 <!--[endif]-->在一個外部程式執行完之前你不能得到他的退出狀態 

<!--[if !supportLists]-->2、 <!--[endif]-->在你的外部程式開始執行的時候你必須馬上控制輸入、輸出、出錯這些流。 

<!--[if !supportLists]-->3、 <!--[endif]-->你必須用Runtime.exec()去執行程式 

<!--[if !supportLists]-->4、 <!--[endif]-->你不能象命令列一樣使用Runtime.exec()。
12:35
評論 / 瀏覽 (0 / 11)
分類:程式語言
2011-11-30
縮略顯示
FileInputStream/FileOutputStream的應用
javafileoutputstreamfileinputstream
這是一對繼承於InputStream和OutputStream的類,用於本地檔案讀寫(二進位制格式讀寫並且是順序讀寫,讀和寫要分別建立出不同的檔案流物件); 

本地檔案讀寫程式設計的基本過程為: 

①  生成檔案流物件(對檔案讀操作時應該為FileInputStream類,而檔案寫應該為FileOutputStream類); 

②  呼叫FileInputStream或FileOutputStream類中的功能函式如read()、write(int b)等)讀寫檔案內容; 

③  關閉檔案(close())。 

例項:流檔案讀寫 

流檔案的單元是位元組,所以它不但可以讀寫文字檔案,也可以讀寫圖片、聲音、影像檔案,這種特點非常有用,因為我們可以把這種檔案變成流,然後在網路上傳輸。 

問題是有了通用的流檔案以後,為什麼還要專門的字元流呢?這是因為文字可以用不同的方式儲存,可以是普通的文字(UTF-8編碼方式),ASCII文字和Unicode文字,字元流物件可以進行必要的轉換,從而讀出正確的文字。 

有人認為流檔案不能讀寫文字檔案,這其實是個誤會,因為文字檔案本質上也是由位元組組成的,當然是流檔案的一種。作為讀寫檔案的全體,這是沒問題的,但是,如果要處理每次讀入的內容,就最好使用字元流。 

所以在文字檔案處理時,使用字元流是個最常用的方法。 

樣例: 

import java.io.*; 

public class FileStreamDemo { 

public static void main(String[] args) throws IOException { 

//建立兩個檔案,face.gif是已經存在檔案,newFace.gif是新建立的檔案 

File inFile = new File("face.gif"); 

File outFile = new File("newFace.gif"); 

//建立流檔案讀入與寫出類 

FileInputStream inStream = new FileInputStream(inFile); 

FileOutputStream outStream = new FileOutputStream(outFile); 

//通過available方法取得流的最大字元數 

byte[] inOutb = new byte[inStream.available()]; 

inStream.read(inOutb);  //讀入流,儲存在byte陣列 

outStream.write(inOutb);  //寫出流,儲存在檔案newFace.gif中 

inStream.close(); 

outStream.close(); 

} 

} 

例項:讀寫任意大檔案應用 

因為byte陣列最大儲存值不超過64M,所以當一個檔案大於60M 的時候,需要分開幾個流操作。我們把上面的程式作一個修改,就可以寫入任意大小的檔案。這個程式應用了FileInputStream類的方法如下: 

read(byte[] b,int off,int len) 

把特定位置的流內容讀入陣列,已經讀入byte[]陣列的內容,會在流檔案中刪除。 

程式執行的結果會產生一個新檔案。 

樣例: 

import java.io.*; 

public class FileStreamDemo2 { 

public static void main(String[] args) throws IOException { 

//建立兩個檔案 

File inFile = new File("tcty36.rm"); 

File outFile = new File("newtcty36.rm"); 

//最大的流為60Mb,當檔案的容量大於60Mb的時候便分開流 

final int MAX_BYTE = 60000000; 

long streamTotal = 0;  //接受流的容量 

int streamNum = 0;  //流需要分開的數量 

int leave = 0;  //檔案剩下的字元數 

byte[] inOutb;  //byte陣列接受檔案的資料 

//建立流檔案讀入與寫出類 

FileInputStream inStream = new FileInputStream(inFile); 

FileOutputStream outStream = new FileOutputStream(outFile); 

//通過available方法取得流的最大字元數 

streamTotal = inStream.available(); 

//取得流檔案需要分開的數量 

streamNum = (int)Math.floor(streamTotal/MAX_BYTE); 

//分開檔案之後,剩餘的數量 

leave = (int)streamTotal % MAX_BYTE; 

//檔案的容量大於60Mb時進入迴圈 

if (streamNum > 0) { 

for(int i = 0; i < streamNum; ++i){ 

inOutb = new byte[MAX_BYTE]; 

//讀入流,儲存在byte陣列 

inStream.read(inOutb, 0, MAX_BYTE); 

outStream.write(inOutb);  //寫出流 

outStream.flush();  //更新寫出的結果 

} 

} 

//寫出剩下的流資料 

inOutb = new byte[leave]; 

inStream.read(inOutb, 0, leave); 

outStream.write(inOutb); 

outStream.flush(); 

inStream.close(); 

outStream.close(); 

} 

} 

六、管道PipedInputStream/PipedOutputStream類: 

當需要在兩個執行緒中讀寫資料的時候,由於執行緒的併發執行,讀寫的同步問題可能會發生困難,這時候可以使用管道,管道事實上是一個佇列。 

管道是由系統維護的一個緩衝區,當然程式設計師也可以自己直接指定該緩衝區的大小(只需要設定管道流類中的PIPE_SIZE屬性的值)。當生產者生產出資料後,只需要將資料寫入管道中,消費者只需要從管道中讀取所需要的資料。利用管道的這種機制,可以將一個執行緒的輸出結果直接連線到另一個執行緒的輸入埠,實現兩者之間的資料直接傳送。 

執行緒1 
執行緒2 
臨時檔案 
管道 

1.管道的連線: 

方法之一是通過建構函式直接將某一個程式的輸出作為另一個程式的輸入,在定義物件時指明目標管道物件 

PipedInputStream pInput=new PipedInputStream(); 

PipedOutputStream pOutput= new PipedOutputStream(pInput); 

方法之二是利用雙方類中的任一個成員函式 connect()相連線 

PipedInputStream pInput=new PipedInputStream(); 

PipedOutputStream pOutput= new PipedOutputStream(); 

pinput.connect(pOutput); 

2.管道的輸入與輸出: 

輸出管道物件呼叫write()成員函式輸出資料(即向管道的輸入端傳送資料);而輸入管道物件呼叫read()成員函式可以讀起資料(即從輸出管道中獲得資料)。這主要是藉助系統所提供的緩衝機制來實現的。 

例項:Java的管道的輸入與輸出 

import java.io.*; 

public class PipedIO //程式執行後將sendFile檔案的內容拷貝到receiverFile檔案中 

{ 

public static void main(String args[]) 

{ 

try 

{ 

//構造讀寫的管道流物件 

PipedInputStream pis=new PipedInputStream(); 

PipedOutputStream pos=new PipedOutputStream(); 

//實現關聯 

pos.connect(pis); 

//構造兩個執行緒,並且啟動。 

new Sender(pos,"c:\\text2.txt").start(); 

new Receiver(pis,"c:\\text3.txt").start(); 

} 

catch(IOException e) 

{ 

System.out.println("Pipe Error"+ e); 

} 

} 

} 

//執行緒傳送 

class Sender extends Thread 

{ 

PipedOutputStream pos; 

File file; 

//構造方法 

Sender(PipedOutputStream pos, String fileName) 

{ 

this.pos=pos; 

file=new File(fileName); 

} 

//執行緒執行方法 

public void run() 

{ 

try 

{ 

//讀檔案內容 

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; 

//構造方法 

Receiver(PipedInputStream pis, String fileName) 

{ 

this.pis=pis; 

file=new File(fileName); 

} 

//執行緒執行 

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); 

} 

} 

} 

七、隨機檔案讀寫:RandomAccessFile類 

它直接繼承於Object類而非InputStream/OutputStream類,從而可以實現讀寫檔案中任何位置中的資料(只需要改變檔案的讀寫位置的指標)。 

程式設計步驟: 

① 生成流物件並且指明讀寫型別; 

② 移動讀寫位置; 

③ 讀寫檔案內容; 

④ 關閉檔案。 

另外由於RandomAccessFile類實現了DataOutput與DataInput介面,因而利用它可以讀寫Java中的不同型別的基本型別資料(比如採用readLong()方法讀取長整數,而利用readInt()方法可以讀出整數值等)。 

程式例項: 

利用隨機資料流RandomAccessFile類來實現記錄使用者在鍵盤的輸入,每執行一次,將使用者的鍵盤輸入儲存在指定的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()); 

//將使用者從鍵盤輸入的內容新增到檔案的尾部 

myFileStream.close(); 

} 

catch(IOException e) 

{ 

} 

} 

} 

八、DataInput/DataOutput介面: 

實現與機器無關的各種資料格式讀寫(如readChar() 、readInt()、readLong()、readFloat(),而readLine()將返回一個String)。其中 RandomAccessFile類實現了該介面,具有比FileInputStream或FileOutputStream類更靈活的資料讀寫方式。
12:27
評論 / 瀏覽 (0 / 17)
分類:程式語言
2011-11-28
縮略顯示
Linux C 建立目錄函式mkdir相關
linuxc
I.Linux C 建立目錄函式mkdir的mode設定問題 

函式原型: 

#include <sys/stat.h> 

int mkdir(const char *path, mode_t mode); 

引數: 

path是目錄名 

mode是目錄許可權 

返回值: 

返回0 表示成功, 返回 -1表示錯誤,並且會設定errno值。 

mode模式位: 

mode 表示新目錄的許可權,可以取以下值: 

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); 

這樣就建立了一個newdir目錄,許可權通過ls -al 檢視為 

drwxr-xr-x 

跟用linux命令mkdir建立的目錄許可權位一致。 



II. linux下C語言建立多級目錄 

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 程式設計:建立一個執行緒,監視某個目錄,一旦目錄裡出現新的檔案,就將檔案轉移到指定的目錄裡去。 
/* 
標頭檔案 
*/ 
#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; 
} 
//如果這個目錄裡 還有目錄,可以在這加判斷 
//這裡假設初始為空目錄 
strcat(filename1,dt->d_name); 
strcat(filename2,dt->d_name); 
//如果程式資源較少可以直接用linux系統命令 

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)
分類:程式語言
2011-11-28
縮略顯示
Linux下的C程式設計實戰之檔案系統程式設計
linuxc程式設計
1.Linux檔案系統 

  Linux支援多種檔案系統,如ext、ext2、minix、iso9660、msdos、fat、vfat、nfs等。在這些具體檔案系統的上層,Linux提供了虛擬檔案系統(VFS)來統一它們的行為,虛擬檔案系統為不同的檔案系統與核心的通訊提供了一致的介面。 

linux下的c語言開發 

  在Linux平臺下對檔案程式設計可以使用兩類函式:(1)Linux作業系統檔案API;(2)C語言I/O庫函式。 前者依賴於Linux系統呼叫,後者實際上與作業系統是獨立的,因為在任何作業系統下,使用C語言I/O庫函式操作檔案的方法都是相同的。本章將對這兩種方法進行例項講解。 

  2.Linux檔案API 

  Linux的檔案操作API涉及到建立、開啟、讀寫和關閉檔案。 

  建立 

int creat(const char *filename, mode_t mode); 

  引數mode指定新建檔案的存取許可權,它同umask一起決定檔案的最終許可權(mode&umask),其中umask代表了檔案在建立時需要去掉的一些存取許可權。umask可通過系統呼叫umask()來改變: 

int umask(int newmask); 

  該呼叫將umask設定為newmask,然後返回舊的umask,它隻影響讀、寫和執行許可權。 

  開啟 

int open(const char *pathname, int flags); 
int open(const char *pathname, int flags, mode_t mode); 

  open函式有兩個形式,其中pathname是我們要開啟的檔名(包含路徑名稱,預設是認為在當前路徑下面),flags可以去下面的一個值或者是幾個值的組合: 

標誌 含義 
O_RDONLY 以只讀的方式開啟檔案 
O_WRONLY 以只寫的方式開啟檔案 
O_RDWR 以讀寫的方式開啟檔案 
O_APPEND 以追加的方式開啟檔案 
O_CREAT 建立一個檔案 
O_EXEC 如果使用了O_CREAT而且檔案已經存在,就會發生一個錯誤 
O_NOBLOCK 以非阻塞的方式開啟一個檔案 
O_TRUNC 如果檔案已經存在,則刪除檔案的內容 
  

  O_RDONLY、O_WRONLY、O_RDWR三個標誌只能使用任意的一個。 

  如果使用了O_CREATE標誌,則使用的函式是int open(const char *pathname,int flags,mode_t mode); 這個時候我們還要指定mode標誌,用來表示檔案的訪問許可權。mode可以是以下情況的組合: 

標誌 含義 
S_IRUSR 使用者可以讀 
S_IWUSR 使用者可以寫 
S_IXUSR 使用者可以執行 
S_IRWXU 使用者可以讀、寫、執行 
S_IRGRP 組可以讀 
S_IWGRP 組可以寫 
S_IXGRP 組可以執行 
S_IRWXG 組可以讀寫執行 
S_IROTH 其他人可以讀 
S_IWOTH 其他人可以寫 
S_IXOTH 其他人可以執行 
S_IRWXO 其他人可以讀、寫、執行 
S_ISUID 設定使用者執行ID 
S_ISGID 設定組的執行ID 

  除了可以通過上述巨集進行“或”邏輯產生標誌以外,我們也可以自己用數字來表示,Linux總共用5個數字來表示檔案的各種許可權:第一位表示設定使用者ID;第二位表示設定組ID;第三位表示使用者自己的許可權位;第四位表示組的許可權;最後一位表示其他人的許可權。每個數字可以取1(執行許可權)、2(寫許可權)、4(讀許可權)、0(無)或者是這些值的和。例如,要建立一個使用者可讀、可寫、可執行,但是組沒有許可權,其他人可以讀、可以執行的檔案,並設定使用者ID位。那麼,我們應該使用的模式是1(設定使用者ID)、0(不設定組 ID)、7(1+2+4,讀、寫、執行)、0(沒有許可權)、5(1+4,讀、執行)即10705: 

open("test", O_CREAT, 10705); 

  上述語句等價於: 

open("test", O_CREAT, S_IRWXU | S_IROTH | S_IXOTH | S_ISUID ); 

  如果檔案開啟成功,open函式會返回一個檔案描述符,以後對該檔案的所有操作就可以通過對這個檔案描述符進行操作來實現。 

  讀寫 

  在檔案開啟以後,我們才可對檔案進行讀寫了,Linux中提供檔案讀寫的系統呼叫是read、write函式: 

int read(int fd, const void *buf, size_t length); 
int write(int fd, const void *buf, size_t length); 

  其中引數buf為指向緩衝區的指標,length為緩衝區的大小(以位元組為單位)。函式read()實現從檔案描述符fd所指定的檔案中讀取 length個位元組到buf所指向的緩衝區中,返回值為實際讀取的位元組數。函式write實現將把length個位元組從buf指向的緩衝區中寫到檔案描述符fd所指向的檔案中,返回值為實際寫入的位元組數。 

  以O_CREAT為標誌的open實際上實現了檔案建立的功能,因此,下面的函式等同creat()函式: 

int open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode); 

  定位 

  對於隨機檔案,我們可以隨機的指定位置讀寫,使用如下函式進行定位: 

int lseek(int fd, offset_t offset, int whence); 

  lseek()將檔案讀寫指標相對whence移動offset個位元組。操作成功時,返回檔案指標相對於檔案頭的位置。引數whence可使用下述值: 

  SEEK_SET:相對檔案開頭 
  SEEK_CUR:相對檔案讀寫指標的當前位置 
  SEEK_END:相對檔案末尾 

  offset可取負值,例如下述呼叫可將檔案指標相對當前位置向前移動5個位元組: 

lseek(fd, -5, SEEK_CUR); 

  由於lseek函式的返回值為檔案指標相對於檔案頭的位置,因此下列呼叫的返回值就是檔案的長度: 

lseek(fd, 0, SEEK_END); 

  關閉 

  當我們操作完成以後,我們要關閉檔案了,只要呼叫close就可以了,其中fd是我們要關閉的檔案描述符: 

int close(int fd); 

  例程:編寫一個程式,在當前目錄下建立使用者可讀寫檔案“hello.txt”,在其中寫入“Hello, software weekly”,關閉該檔案。再次開啟該檔案,讀取其中的內容並輸出在螢幕上。 

#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); /* 建立並開啟檔案 */ 
 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); /* 讀取檔案內容 */ 
 str[len] = '\0'; 
 printf("%s\n", str); 
 close(fd); 
} 

  編譯並執行,執行結果如下圖: 

linux 

  3.C語言庫函式 

  C庫函式的檔案操作實際上是獨立於具體的作業系統平臺的,不管是在DOS、Windows、Linux還是在VxWorks中都是這些函式: 

  建立和開啟 

FILE *fopen(const char *path, const char *mode); 

  fopen()實現開啟指定檔案filename,其中的mode為開啟模式,C語言中支援的開啟模式如下表: 

標誌 含義 
r, rb 以只讀方式開啟 
w, wb 以只寫方式開啟。如果檔案不存在,則建立該檔案,否則檔案被截斷 
a, ab 以追加方式開啟。如果檔案不存在,則建立該檔案 
r+, r+b, rb+ 以讀寫方式開啟 
w+, w+b, wh+ 以讀寫方式開啟。如果檔案不存在時,建立新檔案,否則檔案被截斷 
a+, a+b, ab+ 以讀和追加方式開啟。如果檔案不存在,建立新檔案 

  其中b用於區分二進位制檔案和文字檔案,這一點在DOS、Windows系統中是有區分的,但Linux不區分二進位制檔案和文字檔案。 

  讀寫 

  C庫函式支援以字元、字串等為單位,支援按照某中格式進行檔案的讀寫,這一組函式為: 

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()實現從流stream中讀取加n個欄位,每個欄位為size位元組,並將讀取的欄位放入ptr所指的字元陣列中,返回實際已讀取的欄位數。在讀取的欄位數小於num時,可能是在函式呼叫時出現錯誤,也可能是讀到檔案的結尾。所以要通過呼叫feof()和ferror()來判斷。 

  write()實現從緩衝區ptr所指的陣列中把n個欄位寫到流stream中,每個欄位長為size個位元組,返回實際寫入的欄位數。 

  另外,C庫函式還提供了讀寫過程中的定位能力,這些函式包括 

int fgetpos(FILE *stream, fpos_t *pos); 
int fsetpos(FILE *stream, const fpos_t *pos); 
int fseek(FILE *stream, long offset, int whence); 
等。 

  關閉 

  利用C庫函式關閉檔案依然是很簡單的操作: 

int fclose (FILE *stream); 

  例程:將第2節中的例程用C庫函式來實現。 

#include <stdio.h> 
#define LENGTH 100 
main() 
{ 
 FILE *fd; 
 char str[LENGTH]; 

 fd = fopen("hello.txt", "w+"); /* 建立並開啟檔案 */ 
 if (fd) 
 { 
  fputs("Hello, Software Weekly", fd); /* 寫入Hello, software weekly字串 */ 
  fclose(fd); 
 } 

 fd = fopen("hello.txt", "r"); 
 fgets(str, LENGTH, fd); /* 讀取檔案內容 */ 
 printf("%s\n", str); 
 fclose(fd); 
} 

  4.小結 

  Linux提供的虛擬檔案系統為多種檔案系統提供了統一的介面,Linux的檔案程式設計有兩種途徑:基於Linux系統呼叫;基於C庫函式。這兩種程式設計所涉及到檔案操作有新建、開啟、讀寫和關閉,對隨機檔案還可以定位。本章對這兩種程式設計方法都給出了具體的例項。
14:00
評論 / 瀏覽 (0 / 19)
分類:程式語言
2011-11-28
縮略顯示
基本IO函式的使用(open,write,read)(一)
linux c
首先感謝作者的工作,謝謝了,轉到這裡都是我需要過的 

=>#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 

摘要:本文簡單介紹檔案操作的三個函式(open,read,write)的基本用法。 
詳細說明了open函式的用法。 

    作者:zieckey (zieckey@yahoo.com.cn) 
    All Rights Reserved! 

所需標頭檔案: 
#include<sys/types.h> 
#include<sys/stat.h> 
#include<fcntl.h> 

函式定義: 
int open( const char * pathname, int flags); 
int open( const char * pathname,int flags, mode_t mode); 

函式說明: 
引數 pathname 指向欲開啟的檔案路徑字串。下列是引數 flags 所能使用的旗標: 
O_RDONLY 以只讀方式開啟檔案 
O_WRONLY 以只寫方式開啟檔案 
O_RDWR以可讀寫方式開啟檔案。 
上述三種旗標是互斥的,也就是不可同時使用,但可與下列的旗標利用 OR(|)運算子組合。 

O_CREAT 若欲開啟的檔案不存在則自動建立該檔案。 
O_EXCL 如果 O_CREAT 也被設定,     此指令會去檢查檔案是否存在。檔案若不存在則建立該檔案,         
   否則將導致開啟檔案錯誤。 此外,若 O_CREAT 與 O_EXCL 同時設定,  並且欲開啟的檔案為符號連線,則會開啟檔案失敗。 
O_NOCTTY 如果欲開啟的檔案為終端機裝置時,則不會將該終端機當成程式控制終端機。 
O_TRUNC 若檔案存在並且以可寫的方式開啟時,此旗標會令檔案長度清為 0,而原來存於該檔案的資料也會消失。
O_APPEND 當讀寫檔案時會從檔案尾開始移動,        也就是所寫入的資料會以附加的方式加入到檔案後面。 
O_NONBLOCK 以不可阻斷的方式開啟檔案,也就是無論有無資料讀取或等待,都會立即返回程式之中。 
O_NDELAY 同 O_NONBLOCK。 
O_SYNC 以同步的方式開啟檔案。 
O_NOFOLLOW 如果引數 pathname 所指的檔案為一符號連線,則會令開啟檔案失敗。 
O_DIRECTORY 如果引數 pathname 所指的檔案並非為一目錄,  則 
    會令開啟檔案失敗。此為 Linux2.2 以後特有的旗標,以避免一些系 
    統安全問題。引數 mode 則有下列數種組合,只有在建立新檔案時 
    才會生效,此外真正建檔案時的許可權會受到 umask 值所影響,因此 
    該檔案許可權應該為(mode-umaks). 
S_IRWXU00700 許可權, 代表該檔案所有者具有可讀、    可寫及可執行的許可權。 
S_IRUSR 或 S_IREAD,00400 許可權,代表該檔案所有者具有可讀取的許可權。 
S_IWUSR 或 S_IWRITE,00200 許可權,代表該檔案所有者具有可寫入的許可權。 
S_IXUSR 或 S_IEXEC,00100 許可權,代表該檔案所有者具有可執行的許可權。 
S_IRWXG 00070 許可權,代表該檔案使用者組具有可讀、    可寫及可執行的許可權。 
S_IRGRP 00040 許可權,代表該檔案使用者組具有可讀的許可權。 
S_IWGRP 00020 許可權,代表該檔案使用者組具有可寫入的許可權。 
S_IXGRP 00010 許可權,代表該檔案使用者組具有可執行的許可權。 
S_IRWXO 00007 許可權,代表其他使用者具有可讀、可寫及可執行的許可權。 
S_IROTH 00004 許可權,代表其他使用者具有可讀的許可權 
S_IWOTH 00002 許可權,代表其他使用者具有可寫入的許可權。 
S_IXOTH 00001 許可權,代表其他使用者具有可執行的許可權。 


返回值: 
     若所有欲核查的許可權都通過了檢查則返回 0 值,表示成功,只要有 一個許可權被禁止則返回-1。 

錯誤程式碼: 
EEXIST 引數 pathname 所指的檔案已存在,卻使用了 O_CREAT和 O_EXCL 旗標 
EACCESS 引數 pathname 所指的檔案不符合所要求測試的許可權。 
EROFS 欲測試寫入許可權的檔案存在於只讀檔案系統內。 
EFAULT 引數 pathname 指標超出可存取記憶體空間。 
EINVAL 引數 mode 不正確。 
ENAMETOOLONG 引數 pathname 太長。 
ENOTDIR 引數 pathname 不是目錄。 
ENOMEM 核心記憶體不足。 
ELOOP 引數 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 );//以可讀寫的方式開啟一個檔案,如果不存在則建立該檔案 

    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) );//讀取檔案內容儲存到buffer指定的字串陣列中,返回讀取的字元個數

    close( fd ); 
    printf( "%s", buffer ); 
    
    return 0; 
}
13:44
評論 / 瀏覽 (0 / 3)
分類:程式語言
2011-11-18
縮略顯示
Android讀寫檔案
android
一、       從resource中的raw資料夾中獲取檔案並讀取資料(資原始檔只能讀不能寫) 

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的編碼型別選擇合適的編碼,如果不調整會亂碼 

   in.close();            

   }catch(Exception e){ 

      e.printStackTrace();         

   } 

myTextView.setText(res);//把得到的內容顯示在TextView上 


二、       從asset中獲取檔案並讀取資料(資原始檔只能讀不能寫) 

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把本地計算機上的檔案copy到sdcard上去,adb.exe push e:/Y.txt /sdcard/, 不可以用adb.exe push e:\Y.txt \sdcard\ 同樣: 把模擬器上的檔案copy到本地計算機上用: 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是可以看到模擬器檔案存放目錄的結構的 

   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/目錄(相當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)
分類:移動開發
2011-11-09
縮略顯示
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   

目前計算機中用得最廣泛的字符集及其編碼,是由美國國家標準局(ANSI)制定的ASCII碼(American Standard Code for Information Interchange,美國標準資訊交換碼),它已被國際標準化組織(ISO)定為國際標準,稱為ISO 646標準。適用於所有拉丁文字字母,ASCII碼有7位碼和8位碼兩種形式。  

  因為1位二進位制數可以表示(21=)2種狀態:01;而2位二進位制數可以表示(22)=4種狀態:00011011;依次類推,7位二進位制數可以表示(27=)128種狀態,每種狀態都唯一地編為一個7位的二進位制碼,對應一個字元(或控制碼),這些碼可以排列成一個十進位制序號0~127。所以,7位 ASCII碼是用七位二進位制數進行編碼的,可以表示128個字元。  

  第0~32號及第127號(共34個)是控制字元或通訊專用字元,如控制符:LF(換行)、CR(回車)、FF(換頁)、DEL(刪除)、BEL(振鈴)等;通訊專用字元:SOH(文頭)、EOT(文尾)、ACK(確認)等; 

  第33~126號(共94個)是字元,其中第48~57號為0~9十個阿拉伯數字;65~90號為26個大寫英文字母,97~122號為26個小寫英文字母,其餘為一些標點符號、運算子號等。  

  注意:在計算機的儲存單元中,一個ASCII碼值佔一個位元組(8個二進位制位),其最高位(b7)用作奇偶校驗位。所謂奇偶校驗,是指在程式碼傳送過程中用來檢驗是否出現錯誤的一種方法,一般分奇校驗和偶校驗兩種。奇校驗規定:正確的程式碼一個位元組中1的個數必須是奇數,若非奇數,則在最高位b7添1;偶校驗規定:正確的程式碼一個位元組中1的個數必須是偶數,若非偶數,則在最高位b7添1。  
    第128~255號為擴充套件字元(不常用),如需要請下載:完整的8位ASCII字元表  
09:36
評論 / 瀏覽 (0 / 7)
分類:非技術
2011-11-03
縮略顯示
Android輸入事件流程中的EventHub分析及原始碼演示
android
Android2.3的輸入事件流程與以前版本有了較大的不同,這裡做一下詳細的分析,最後我把自己分析時用的演示程式碼放在了這裡: 

http://code.google.com/p/flying-on-android/ 

下面的分析都是基於這些原始碼的,大家可以下載下來一邊看原始碼一邊看文件。原始碼裡只要關注FlyingEvent這個類就可以了。如果只想看一下演示結果,可以直接把包裡的flying放到機器的/system/bin目錄執行,開啟logcat後就可以看到演示輸出。執行程式時,機器螢幕會有異象產生,很正常,因為這個程式原本是用於顯示SurfaceFlinger的,這次為了演示EventHub稍微改了一下。大家只要關注 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為視窗系統提供服務,EventHub.cpp主要用來讀取裝置檔案中的RawEvent,而InputReader.cpp和InputDispatcher.cpp算是它們之間的對接層。 



它們的關係是:WindowManagerService通過InputManager提供的介面開啟一個執行緒驅動InputReader不斷地從 /dev/input/目錄下面的裝置檔案讀取事件,然後通過InputDispatcher分發給連線到WindowManagerService服務的客戶端。 

InputReader從裝置檔案中讀取的是RawEvent,在交給InputDispatcher進行分發之前,它需要先把RawEvent進行轉化分類,拆分成KeyEvent、MotionEvent、TrackEvent各種型別等。這篇文章主要關注的就是這個RawEvent的拆分過程,所以我們的重點在EventHub.cpp中。並且,為了簡單化分析過程,在這裡我的分析只關注觸控式螢幕事件。看它是如何從RawEvent被拆分成應用層使用者事件MotionEvent的。 



看下面的分析之前,最好先去上面提到的地址把原始碼下載下來,參照裡面的FlyingEvent.cpp。 



整個過程大致分成這麼幾步: 

一、初始化。 

先new一個EventHub的例項:mEventHub(new EventHub), 

接下來,開啟一個執行緒通過mEventHub不停地從裝置檔案中讀取RawEvent並處理: 

while (1) { 

    RawEvent event; 

    mEventHub->getEvent(&event); 

    process(event); 

} 

EventHub在初始化的時候做一些事情, 

1、搜尋當前的輸入裝置每搜尋到一個就會產生一個型別為DEVICE_ADDED的事件,當讀取這種RawEvent時,InputReader會把搜尋到的這個裝置記錄下來。 

2、如果搜尋到了鍵盤時,就會載入鍵盤佈局檔案。載入完成後產生一個型別為FINISHED_DEVICE_SCAN的事件。這樣,後邊從驅動讀取使用者按鍵時,就會去載入的鍵盤佈局檔案中尋找對映的鍵值封裝成KeyEvent返回給使用者。 



二、EventHub初始化完畢後,就開始等待使用者輸入。執行緒一直阻塞在mEventHub->getEvent(&event),直到有使用者事件產生才會返回。 

當有一個事件產生時,傳遞給process進行處理。 



三、事件拆分 

FlyingEvent.process裡面主要呼叫了FlyingEvent.consume方法來處理使用者事件。這裡只分析touch事件。touch事件可以分為三種:down,move,up。 

down型別的touch事件需要四個RawEvent來完成,第一個是X座標(ABS_X),第二個是Y座標(ABS_Y),第三個代表方向(ABS_PRESSURE)(0的時候是up,1的時候是down,所以這裡應該是1),第四個是結束標誌(SYN_REPORT)。 

move型別的touch事件需要三個RawEvent來完成,第一個是X座標,第二個是Y座標,第三個是結束標誌。 

up型別的touch事件需要兩個RawEvent來完成,第一個代表方向(0的時候是up,1的時候是down,所以這裡應該是0),第四個是結束標誌。 

可能你已經注意到了up事件是沒有座標資訊的,它的座標資訊與down(沒有move時)或最後一個move(down和up之間有move事件產生)事件的座標相同。 



從FlyingEvent.consume方法中,每一個事件最終都會生成一個TouchEvent,然後呼叫printTouchEvent進行列印,最後把它儲存到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)
分類:移動開發
2011-10-21
縮略顯示
svn還原恢復
svn
1.對檔案和目錄的修改還原 
svn revert PATH... 
描述 
恢復所有對檔案和目錄的修改,並且解決所有的衝突狀態。svn revert不會只是恢復工作拷貝中一個專案的內容,也包括了對屬性修改的恢復。最終,你可以使用它來取消所有已經做過的預定操作(例如,檔案預定要新增或刪除可以“恢復”)。 

例子 
丟棄對一個檔案的修改: 

$ svn revert foo.c 
Reverted foo.c 

如果你希望恢復一整個目錄的檔案,可以使用--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當前版本差異 
svn status -v path(顯示檔案和子目錄狀態) 
簡寫:svn st 
第一列保持相同,第二列顯示工作版本號,第三和第四列顯示最後一次修改的版本號和修改人。 
另外,可執行script -q tty.log後,就開始記錄終端的輸入輸出資訊,結束的時候按ctrl+D即可得到終端的內容檔案tty.log 

4. svn比較差異 
svn diff path(將修改的檔案與基礎版本比較) 
例如:svn diff test.php 
svn diff -r m:n path(對版本m和版本n比較差異) 

注:svn status、svn diff和 svn revert這三條命令在沒有網路的情況下也可以執行的,原因是svn在本地的.svn中保留了本地版本的原始拷貝。 

11:19
評論 / 瀏覽 (0 / 43)
分類:非技術
2011-10-18
縮略顯示
linux下檢視記憶體使用情況
在Linux下檢視記憶體我們一般用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 

下面是對這些數值的解釋: 
total:總計實體記憶體的大小。 
used:已使用多大。 
free:可用有多少。 
Shared:多個程式共享的記憶體總額。 
Buffers/cached:磁碟快取的大小。 
第三行(-/+ buffers/cached): 
used:已使用多大。 
free:可用有多少。 
第四行就不多解釋了。 
區別:第二行(mem)的used/free與第三行(-/+ buffers/cache) used/free的區別。 這兩個的區別在於使用的角度來看,第一行是從OS的角度來看,因為對於OS,buffers/cached 都是屬於被使用,所以他的可用記憶體是16176KB,已用記憶體是3250004KB,其中包括,核心(OS)使用+Application(X, oracle,etc)使用的+buffers+cached. 
第三行所指的是從應用程式角度來看,對於應用程式來說,buffers/cached 是等於可用的,因為buffer/cached是為了提高檔案讀取的效能,當應用程式需在用到記憶體的時候,buffer/cached會很快地被回收。 
所以從應用程式的角度來說,可用記憶體=系統free memory+buffers+cached。 
如上例: 
2795064=16176+110652+2668236 

接下來解釋什麼時候記憶體會被交換,以及按什麼方交換。 當可用記憶體少於額定值的時候,就會開會進行交換。 
如何看額定值: 
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檢視的結果: 
[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檔案的大小(記憶體映象): 
[root@scs-2 tmp]# ll -h /proc/kcore 
-r-------- 1 root root 4.1G Jun 12 12:04 /proc/kcore 

備註: 

佔用記憶體的測量 

測量一個程式佔用了多少記憶體,linux為我們提供了一個很方便的方法,/proc目錄為我們提供了所有的資訊,實際上top等工具也通過這裡來獲取相應的資訊。 

/proc/meminfo 機器的記憶體使用資訊 

/proc/pid/maps pid為程式號,顯示當前程式所佔用的虛擬地址。 

/proc/pid/statm 程式所佔用的記憶體 

[root@localhost ~]# cat /proc/self/statm 

654 57 44 0 0 334 0 

輸出解釋 

CPU 以及CPU0。。。的每行的每個引數意思(以第一行為例)為: 

引數 解釋 /proc//status 

Size (pages) 任務虛擬地址空間的大小 VmSize/4 

Resident(pages) 應用程式正在使用的實體記憶體的大小 VmRSS/4 

Shared(pages) 共享頁數 0 

Trs(pages) 程式所擁有的可執行虛擬記憶體的大小 VmExe/4 

Lrs(pages) 被映像到任務的虛擬記憶體空間的庫的大小 VmLib/4 

Drs(pages) 程式資料段和使用者態的棧的大小 (VmData+ VmStk )4 

dt(pages) 04 

檢視機器可用記憶體 

/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命令檢視機器空閒記憶體時,會發現free的值很小。這主要是因為,在linux中有這麼一種思想,記憶體不用白不用,因此它儘可能的cache和buffer一些資料,以方便下次使用。但實際上這些記憶體也是可以立刻拿來使用的。 

所以 空閒記憶體=free+buffers+cached=total-used 
17:52
評論 / 瀏覽 (0 / 13)
分類:作業系統
2011-08-29
縮略顯示
android 映象製作方法
android
一:update.zip包的製作 
   1:新建一個目標,在此目錄下準備好需要的檔案,如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 //根據需要適當修改些指令碼 
      說明:system是要更新的目錄,android-info.txt是板的版本資訊,update-script是輸出檔名 
   3:建立一個目錄名稱為META-INF/com/google/android,把上面生成的指令碼放進去 
      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)如果檔案裡有連線,應該在獲取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) 產生要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的映象是隻有檔案系統部分時候可以如第四所示範 
        2:如果recovery為ramdisk形式 

============================================= 
制 作ramdisk的過程。 
1.在/mnt下建立rdmnt 和 rdimg 目錄 
mkdir rdmnt 
  mkdir rdimg 
2.建立一個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.拷貝檔案到掛載目錄中。 
檔案系統目錄在:/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)
分類:移動開發
2011-08-24
縮略顯示
Eclipse下svn屬性設定
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)
分類:移動開發
2011-08-24
縮略顯示
linux/Unix環境下的make和makefile詳解
makelinux指令碼
無論是在linux還是在Unix環境中,make都是一個非常重要的編譯命令。不管是自己進行專案開發還是安裝應用軟體,我們都經常要用到make或make install。利用make工具,我們可以將大型的開發專案分解成為多個更易於管理的模組,對於一個包括幾百個原始檔的應用程式,使用make和 makefile工具就可以簡潔明快地理順各個原始檔之間紛繁複雜的相互關係。而且如此多的原始檔,如果每次都要鍵入gcc命令進行編譯的話,那對程式設計師來說簡直就是一場災難。而make工具則可自動完成編譯工作,並且可以只對程式設計師在上次編譯後修改過的部分進行編譯。因此,有效的利用make和 makefile工具可以大大提高專案開發的效率。同時掌握make和makefile之後,您也不會再面對著Linux下的應用軟體手足無措了。 
  但令人遺憾的是,在許多講述linux應用的書籍上都沒有詳細介紹這個功能強大但又非常複雜的編譯工具。在這裡我就向大家詳細介紹一下make及其描述檔案makefile。 
Makefile檔案 
  Make工具最主要也是最基本的功能就是通過makefile檔案來描述源程式之間的相互關係並自動維護編譯工作。而makefile 檔案需要按照某種語法進行編寫,檔案中需要說明如何編譯各個原始檔並連線生成可執行檔案,並要求定義原始檔之間的依賴關係。makefile 檔案是許多編譯器--包括 Windows NT 下的編譯器--維護編譯資訊的常用方法,只是在整合開發環境中,使用者通過友好的介面修改 makefile 檔案而已。 
  在 UNIX 系統中,習慣使用 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編譯器將會輸出三個目標檔案filea.o、fileb.o和filec.o。假設filea.c和fileb.c都要宣告用到一個名為defs的檔案,但filec.c不用。即在filea.c和fileb.c裡都有這樣的宣告: 
  #include "defs" 
  那麼下面的文件就描述了這些檔案之間的相互聯絡: 
  --------------------------------------------------------- 
   #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由三個目標檔案filea.o、fileb.o和filec.o連結生成。第三行描述瞭如何從prog所依賴的檔案建立可執行檔案。接下來的4、6、8行分別指定三個目標檔案,以及它們所依賴的.c和.h檔案以及defs檔案。而5、7、9行則指定了如何從目標所依賴的檔案建立目標。 
  當filea.c或a.h檔案在編譯之後又被修改,則 make 工具可自動重新編譯filea.o,如果在前後兩次編譯之間,filea.C 和a.h 均沒有被修改,而且 test.o 還存在的話,就沒有必要重新編譯。這種依賴關係在多原始檔的程式編譯中尤其重要。通過這種依賴關係的定義,make 工具可避免許多不必要的編譯工作。當然,利用 Shell 指令碼也可以達到自動編譯的效果,但是,Shell 指令碼將全部編譯任何原始檔,包括哪些不必要重新編譯的原始檔,而 make 工具則可根據目標上一次編譯的時間和目標所依賴的原始檔的更新時間而自動判斷應當編譯哪個原始檔。 
Makefile檔案作為一種描述文件一般需要包含以下內容: 
  ◆ 巨集定義 
  ◆ 原始檔之間的相互依賴關係 
  ◆ 可執行的命令 
  Makefile中允許使用簡單的巨集指代原始檔及其相關編譯資訊,在linux中也稱巨集為變數。在引用巨集時只需在變數前加$符號,但值得注意的是,如果變數名的長度超過一個字元,在引用時就必須加圓括號()。 
  下面都是有效的巨集引用: 
  $(CFLAGS) 
  $2 
  $Z 
  $(Z) 
  其中最後兩個引用是完全一致的。 
  需要注意的是一些巨集的預定義變數,在Unix系統中,$*、$@、$?和$<四個特殊巨集的值在執行命令的過程中會發生相應的變化,而在GNU make中則定義了更多的預定義變數。關於預定義變數的詳細內容, 
  巨集定義的使用可以使我們脫離那些冗長乏味的編譯選項,為編寫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 
   …… 
  --------------------------------------------------------- 
  此時如果執行不帶引數的make命令,將連線三個目標檔案和庫檔案LS;但是如果在make命令後帶有新的巨集定義: 
  make "LIBES= -LL -LS" 
則命令列後面的巨集定義將覆蓋makefile檔案中的巨集定義。若LL也是庫檔案,此時make命令將連線三個目標檔案以及兩個庫檔案LS和LL。 
  在Unix系統中沒有對常量NULL作出明確的定義,因此我們要定義NULL字串時要使用下述巨集定義: 
  STRINGNAME= 
Make命令 
  在make命令後不僅可以出現巨集定義,還可以跟其他命令列引數,這些引數指定了需要編譯的目標檔案。其標準形式為: 
  target1 [target2 …]:[:][dependent1 …][;commands][#…] 
  [(tab) commands][#…] 
  方括號中間的部分表示可選項。Targets和dependents當中可以包含字元、數字、句點和"/"符號。除了引用,commands中不能含有"#",也不允許換行。 
  在通常的情況下命令列引數中只含有一個":",此時command序列通常和makefile檔案中某些定義檔案間依賴關係的描述行有關。如果與目標相關連的那些描述行指定了相關的command序列,那麼就執行這些相關的command命令,即使在分號和(tab)後面的aommand欄位甚至有可能是NULL。如果那些與目標相關連的行沒有指定command,那麼將呼叫系統預設的目標檔案生成規則。 
  如果命令列引數中含有兩個冒號"::",則此時的command序列也許會和makefile中所有描述檔案依賴關係的行有關。此時將執行那些與目標相關連的描述行所指向的相關命令。同時還將執行build-in規則。 
  如果在執行command命令時返回了一個非"0"的出錯訊號,例如makefile檔案中出現了錯誤的目標檔名或者出現了以連字元打頭的命令字串,make操作一般會就此終止,但如果make後帶有"-i"引數,則make將忽略此類出錯訊號。 
  Make命本身可帶有四種引數:標誌、巨集定義、描述檔名和目標檔名。其標準形式為: 
  Make [flags] [macro definitions] [targets] 
  Unix系統下標誌位flags選項及其含義為: 
  -f file  指定file檔案為描述檔案,如果file引數為"-"符,那麼描述檔案指向標準輸入。如果沒有"-f"引數,則系統將預設當前目錄下名為 makefile或者名為Makefile的檔案為描述檔案。在linux中, GNU make 工具在當前工作目錄中按照GNUmakefile、makefile、Makefile的順序搜尋 makefile檔案。 
  -i   忽略命令執行返回的出錯資訊。 
  -s   沉默模式,在執行之前不輸出相應的命令列資訊。 
  -r   禁止使用build-in規則。 
  -n   非執行模式,輸出所有執行命令,但並不執行。 
  -t   更新目標檔案。 
  -q   make操作將根據目標檔案是否已經更新返回"0"或非"0"的狀態資訊。 
  -p   輸出所有巨集定義和目標檔案描述。 
  -d   Debug模式,輸出有關檔案和檢測時間的詳細資訊。 
  linux下make標誌位的常用選項與Unix系統中稍有不同,下面我們只列出了不同部分: 
  -c dir   在讀取 makefile 之前改變到指定的目錄dir。 
  -I dir   當包含其他 makefile檔案時,利用該選項指定搜尋目錄。 
  -h   help文擋,顯示所有的make選項。 
  -w   在處理 makefile 之前和之後,都顯示工作目錄。 
  通過命令列引數中的target ,可指定make要編譯的目標,並且允許同時定義編譯多個目標,操作時按照從左向右的順序依次編譯target選項中指定的目標檔案。如果命令列中沒有指定目標,則系統預設target指向描述檔案中第一個目標檔案。 
  通常,makefile 中還定義有 clean 目標,可用來清除編譯過程中的中間檔案,例如: 
  clean: 
  rm -f *.o 
  執行 make clean 時,將執行 rm -f *.o 命令,最終刪除所有編譯過程中產生的所有中間檔案。 
隱含規則 
  在make 工具中包含有一些內建的或隱含的規則,這些規則定義瞭如何從不同的依賴檔案建立特定型別的目標。Unix系統通常支援一種基於副檔名即檔名字尾的隱含規則。這種字尾規則定義瞭如何將一個具有特定檔名字尾的檔案(例如.c檔案),轉換成為具有另一種檔名字尾的檔案(例如.o檔案): 
  .c:.o 
  $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $< 
  系統中預設的常用副檔名及其含義為: 
  .o  目標檔案 
  .c  C原始檔 
  .f  FORTRAN原始檔 
  .s  彙編原始檔 
  .y  Yacc-C源語法 
  .l  Lex源語法 
  在早期的Unix系統系統中還支援Yacc-C源語法和Lex源語法。在編譯過程中,系統會首先在makefile檔案中尋找與目標檔案相關的.C檔案,如果還有與之相依賴的.y和.l檔案,則首先將其轉換為.c檔案後再編譯生成相應的.o檔案;如果沒有與目標相關的.c檔案而只有相關的.y檔案,則系統將直接編譯.y檔案。 
  而GNU make 除了支援字尾規則外還支援另一種型別的隱含規則--模式規則。這種規則更加通用,因為可以利用模式規則定義更加複雜的依賴性規則。模式規則看起來非常類似於正則規則,但在目標名稱的前面多了一個 % 號,同時可用來定義目標和依賴檔案之間的關係,例如下面的模式規則定義瞭如何將任意一個 file.c 檔案轉換為 file.o 檔案: 
  %.c:%.o 
  $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $< 
#EXAMPLE# 
  下面將給出一個較為全面的示例來對makefile檔案和make命令的執行進行進一步的說明,其中make命令不僅涉及到了C原始檔還包括了Yacc 語法。本例選自"Unix Programmer's Manual 7th Edition, Volume 2A" Page 283-284 
  下面是描述檔案的具體內容: 
  --------------------------------------------------------- 
   #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) 
  ---------------------------------------------------------- 
  通常在描述檔案中應象上面一樣定義要求輸出將要執行的命令。在執行了make命令之後,輸出結果為: 
  $ 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 

  最後的數字資訊是執行"@size make"命令的輸出結果。之所以只有輸出結果而沒有相應的命令列,是因為"@size make"命令以"@"起始,這個符號禁止列印輸出它所在的命令列。 
  描述檔案中的最後幾條命令列在維護編譯資訊方面非常有用。其中"print"命令列的作用是列印輸出在執行過上次"make print"命令後所有改動過的檔名稱。系統使用一個名為print的0位元組檔案來確定執行print命令的具體時間,而巨集$?則指向那些在print 檔案改動過之後進行修改的檔案的檔名。如果想要指定執行print命令後,將輸出結果送入某個指定的檔案,那麼就可修改P的巨集定義: 
  make print "P= cat>zap" 
  在linux中大多數軟體提供的是原始碼,而不是現成的可執行檔案,這就要求使用者根據自己系統的實際情況和自身的需要來配置、編譯源程式後,軟體才能使用。只有掌握了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)
分類:移動開發
2011-08-24
縮略顯示
envsetup.sh指令碼分析
android指令碼
build/envsetup.sh指令碼分析 
在編譯原始碼之前通常需要在android原始碼頂層目錄執行 . ./build/envsetup.sh 目的是為了使用 
指令碼 envsetup.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 
} 
會依次進行如下選擇: 
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 
預設選擇以後會出現: 
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()函式分析: 
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 
經過: 
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) 
#編譯靜態庫 
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) 
#編譯動態庫 
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) 
#使用靜態庫 
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) 
#使用動態庫 
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) 
######################## 
系統變數解析 
LOCAL_MODULE - 編譯的目標物件 
LOCAL_SRC_FILES - 編譯的原始檔 
LOCAL_C_INCLUDES - 需要包含的標頭檔案目錄 
LOCAL_SHARED_LIBRARIES - 連結時需要的外部庫 
LOCAL_PRELINK_MODULE - 是否需要prelink處理 
BUILD_SHARED_LIBRARY - 指明要編譯成動態庫 
LOCAL_PATH - 編譯時的目錄 
$(call 目錄,目錄….) 目錄引入操作符 
如該目錄下有個資料夾名稱 src,則可以這樣寫 $(call src),那麼就會得到 src 目錄的完整路徑 
include $(CLEAR_VARS) -清除之前的一些系統變數 
CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mk 
在 build/core/config.mk 定義 CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mk 
通過include 包含自定義的.mk檔案(即是自定義編譯規則)或是引用系統其他的.mk檔案(系統定義的編譯規則)。 
LOCAL_SRC_FILES - 編譯的原始檔 
可以是.c, .cpp, .java, .S(彙編檔案)或是.aidl等格式 
不同的檔案用空格隔開。如果編譯目錄子目錄,採用相對路徑,如子目錄/檔名。也可以通過$(call 目錄),指明編譯某目錄 
下所有.c/.cpp/.java/.S/ .aidl檔案.追加檔案 LOCAL_SRC_FILES += 檔案 
LOCAL_C_INCLUDES - 需要包含的標頭檔案目錄 
可以是系統定義路徑,也可以是相對路徑. 如該編譯目錄下有個include目錄,寫法是include/*.h 
LOCAL_SHARED_LIBRARIES - 連結時需要的外部共享庫 
LOCAL_STATIC_LIBRARIES - 連結時需要的外部外部靜態 
LOCAL_JAVA_LIBRARIES 加入jar包 
LOCAL_MODULE - 編譯的目標物件 
module 是指系統的 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 應用程式的名字用該變數定義 
./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 - 指明要編譯成動態庫。 
編譯的目標,用include 操作符 
UILD_STATIC_LIBRARY來指明要編譯成靜態庫。 
如果是java檔案的話,會用到系統的編譯指令碼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 編譯靜態JAVA庫 
./build/core/config.mk:59:BUILD_STATIC_JAVA_LIBRARY:= $(BUILD_SYSTEM)/static_java_library.mk 
------------------ 
BUILD_HOST_JAVA_LIBRARY 編譯本機用的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利用事先連結代替執行時連結的方法來加速共享庫的載入,它不僅可以加快起動速度,還可以減少部分記憶體開銷, 
是各種Linux架構上用於減少程式載入時間、縮短系統啟動時間和加快應用程式啟動的很受歡迎的一個工具。程式執行時的 
動態連結尤其是重定位(relocation)的開銷對於大型系統來說是很大的。 
動態連結和載入的過程開銷很大,並且在大多數的系統上, 函式庫並不會常常被更動, 每次程式被執行時所進行的連結 
動作都是完全相同的,對於嵌入式系統來說尤其如此。因此,這一過程可以改在執行時之前就可以預先處理好,即花一些時間 
利用Prelink工具對動態共享庫和可執行檔案進行處理,修改這些二進位制檔案並加入相應的重定位等資訊,節約了本來在程式 
啟動時的比較耗時的查詢函式地址等工作,這樣可以減少程式啟動的時間,同時也減少了記憶體的耗用。 
Prelink的這種做法當然也有代價:每次更新動態共享庫時,相關的可執行檔案都需要重新執行一遍Prelink才能保 
證有效,因為新的共享庫中的符號資訊、地址等很可能與原來的已經不同了,這就是為什麼 android framework程式碼一改動, 
這時候就會導致相關的應用程式重新被編譯。 
這種代價對於嵌入式系統的開發者來說可能稍微帶來一些複雜度,不過好在對使用者來說幾乎是可以忽略的。 
-------------------- 
變數設定為false那麼將不做prelink操作 
LOCAL_PRELINK_MODULE := false 
預設是需要prlink的,同時需要在 build/core/prelink-linux-arm.map 中加入 
libhellod.so 0x96000000 
這個map檔案好像是制定動態庫的地址的,在前面註釋上面有一些地址範圍的資訊,注意庫與庫之間的間隔數, 
如果指定不好的話編譯的時候會提示說地址空間衝突的問題。另外,注意排序,這裡要把數大的放到前面去, 
按照大小降序排序。 
解析 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” 
參考文件: 
動態庫優化——Prelink(預連線)技術 
http://www.eefocus.com/article/09-04/71629s.html 
=============== 
LOCAL_ARM_MODE := arm 
目前Android大部分都是基於Arm處理器的,Arm指令用兩種模式Thumb(每條指令兩個位元組)和arm指令(每條指令四個位元組) 
LOCAL_CFLAGS += -O3 -fstrict-aliasing -fprefetch-loop-arrays 
通過設定編譯器操作,優化級別,-O0表示沒有優化,-O1為預設值,-O3優化級別最高 
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 
根據條件選擇相應的編譯引數 
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

 

相關文章