可能是班門弄斧了,僅share給尚不知道的童鞋。
1. 問題的來源:
為什么我們編譯Android代碼時,需要輸入: source ./build/envsetup.sh 或者 . ./build/envsetup.sh哪? (這里的source和.的作用是一致的), 為什么不可以直接執行envsetup.sh腳步而需要通過source命令執行哪?
2. Linux 環境變量的機制
Linux的環境變量是存儲於RAM中的,每個Process啟動時,OS會往Process的RAM中寫入環境變量,所以每個Process的環境變量間是相互獨立的。 Linux每個Process啟動時的初始環境變量是從其父進程繼承過來的,但是一旦子進程啟動后,那么不會再和父進程的環境變量存在任何依賴關系,子進程的環境變量的更改不會影響父進程,反之亦然。 所以,要控制程序運行時能獲取的環境變量,只能在父進程中寫入。
3. 回答開始的問題
Linux中,標准方式運行Shell Script會導致啟動一個新的shell進程來運行Script。 對於envsetup.sh而言,如果以標准方式執行,那么就會啟動一個新的shell進程來運行,運行完成退回到當前的shell進程(我們的編譯shell環境)。envsetup.sh內部定義了一系列的環境變量和shell函數,期望在我們的編譯環境中被使用。那么,如果使用標准方式(非Source)執行時,這些環境變量和函數的定義將只會在新的shell進程(當前編譯環境所在shell進程的子進程)中生效,當envsetup.sh執行后返回其父進程(當前編譯環境所在shell)時,所有envsetup.sh中定義的環境變量和函數在此編譯環境shell中並沒有生效,違背了我們的意願,后續的編譯就不能引用了,比如mm,mmm都不能引用。 此時就需要使用source命令,在當然shell中使用source命令執行envsetup.sh時,不會fork出新的shell進程來運行,而是直接在當前shell進程中讀取envsetup.sh文件來運行,這樣使得envsetup.sh中的環境變量和函數的定義在當前的用戶編譯環境shell中生效。
4. Android/Linux中環境變量的其他一些說明
由於init是User Space的1號進程,所以在init.rc中 Export的環境變量將在所有的User Space進程中可見。Zygote中設置的環境變量,將在所有的Android APK 進程中可見,但是在Native Process中不可見。 Native的環境變量的讀寫函數是,getenv/setenv Java層的環境變量的讀寫函數是:System.getProperties().getProperty/setProperty 注意和Android Property的區別:System.getproperty/setproperty 另外,由於安全問題(這里不詳述,又是另一個話題)所有具有SUID/SGID屬性的Linux的可執行文件(包括.so)在運行時,會在自身進程中刪除一系列和安全相關的繼承來的環境變量,比如LD_LIBRARY_PATH等,使得在其和其子進程中無法繼承和訪問系統的這些環境變量值。
