Android Bionic C

Bionic C 庫一覽:
介紹:
核心體系

Bionic設計的核心思想是:儘量簡單。
這意味這這個C庫只圍繞着內核提供輕量級的包裝,我們讓它儘量小,不去處理一些細枝末頁的事情。

 

Bionic這個名字,是因爲它由部分BSD和部分linux組成:

它的代碼由BSD C庫和自定義的linux代碼(用於處理線程,進程,信號,和其他事情)混合而成。

所有原始的BSD塊,遵循BSD版權聲明。特定的Bionic部分遵循Android open source project版權聲明。一切發行版都遵循BSd版權。

 

 

架構:


Bionic 當前支持ARM and x86指令集。理論上可以支持更多,但是這需要做點工作(比如,
SYSCALLS.TXT文件中添加系統調用IDS,如下面所述,或者修改動態鏈接器)。

ARM相關代碼在arch-arm/下面,x86相關代碼在arch-x86下面。

 

 

注意,x86版本只能運行在x86 android設備上。我們並沒有聲明說,你能夠在普通 x86 linux發佈版上使用Bionic,(儘管這會很,因此歡迎大家做這樣的補丁程序);

 

Syscall stub

 

每個系統調用函數都由一個小的彙編代碼段實現(稱爲syscall stub),這是由tools/gensyscalls.py工具自動生成的,它從SYSCALL.TXT中取得輸入參數。

SYSCALLS.TXT包含了一份要生成的系統調用塊列表,和相應的系統調用數字標識符(ARMX86不一樣),以及它的簽署。

 

如果你要修改這個文件,你可能要使用tools/checksyscalls.py工具,檢查它裏面是否包含官方linux核心頭文件,如果有不合法的syscall ids,它會報告錯誤。

有時,C庫函數其實就是一個包裝,它內部調用相應的syscall名稱,例如,exit函數由C庫提供,它調用了_exit()這個syscall stub.

 

詳細內容請參考SYSCALLS.TXT文件。

 

 

time_t:

 

time_t32CPU內核上定義爲32位,一個64位的版本需要避免Y2038bug,但是內核的維護者認爲,此刻並不需要。相反,Bionic提供了一個<time64.h>頭文件,定義了一個time64_t類型,和相關的函數,如mktime64(), localtime64(),等等。

 

 

時區管理:

 

 

當前時區的名字取決與TZ環境變量,如果TZ未定義,將會使用名爲'persist.sys.timezone'的系統屬性。

時區數據庫和索引文件放在/system/usr/share/zoneinfo下面,而不是在posix兼容路徑/usr/share/zoneinfo下面。

 

 

 

Off_t:


出於相同的原因,off_t也是32位的,由於BSD的繼承關係,我們定義loff_t型爲64位變量,但是

可以使用typedef 定義off64_t類型,以便使得當前linux代碼移植更簡單。

 

 

Linux核心頭文件:

 

 

Bionic帶來一套自己的cleanLinux內核頭文件,允許用戶空間代碼使用內核特有的聲明(比如,

IOCTLs, structure declarations, constants, 等等... ).他們位於:


./kernel/common,

 
./kernel/arch-arm

 
./kernel/arch-x86

 

這些頭文件由一個工具(kernel/tools/update-all.py)產生,只包含原始Linux內核頭文件中的公有定義。

如果你想知道爲什麼和怎麼做,請參考kernel/README.TXT文件。

 

 


Pthread實現:

 

Bionic's C庫使用他自己的pthread程序包,與其他C庫相比有如下不同點:


-放在一個外部庫中(-lpthread

-開放含有少量符號的鏈接器入口用於動態鏈接


運行時特徵支持(a.k.a. -lrt),也打包在C庫中。基於futexes的實現,儘量提供很短小的代碼實現通用操作,有以下幾點顯著的特徵:


- pthread_mutex_t, pthread_cond_t
 每各類型都只有4個字節.

 
-
 支持Normal, recursive and error-check互斥體,對Normal case下的代碼流程做了很細緻的優化,通常大多數的時候都使用Normal

 
-
 進程共享互斥和條件變量不被支持,它們的實現很複雜,而且Android絕對用不到(android使用其他的進程內同步組件)。

 

注意,通過精心調整代碼流程,他們可能會在未來添加進來,而且不會破壞ABI,(儘管這會使代碼執行變得有點兒慢)

 

-當前沒有讀寫鎖,互斥體的優先權,和其他高級特徵的支持。再說一句,在Android中根本不需要這些,但是在未來可能會被添加進來。

 

 

 

 

pthread_cancel():


pthread_cancel()
Bionic中不被支持,因爲這將使得C庫變得龐大起來,就爲了這點好處不值得。

 

 
基於一下幾點考慮:

 
-
 要正常實現,必須在C庫的多個地方插入pthread cancellation檢測,這會使代碼的統一調試變得非常困難。

 

- 要正常實現,也必須清理資源,象釋放內存,解鎖互斥體,如果cancel恰好發生在complex函數裏(比如在gethostbyname() or fprintf() + 複雜格式化規則裏面)。這會使許多函數的執行變慢。

 
- pthread cancellation
不能停止所有的線程:比如,對於無窮循環,它就無能爲力。

 

- pthread cancellation本身也有缺陷,不好移植。


(see http://advogato.org/person/slamb/diary.html?start=49 for example).


所有這些都與Bionic的設計目標相反,如果你的代碼依賴thread cancellation,請好好考慮下吧。

注意Bionic確實實現了pthread_cleanup_push()pthread_cleanup_pop(),在線程通過pthread_exit()調用退出或者從它的主函數中返回的時候,它可作些清理工作,

 
NND
,不想支持就別支持嘛,非要編這麼多理由來敷衍我們。

 

 

pthread_once():

 

不要在pthread_once()的回調函數中調用fork(),這麼做的話,會在下次調用pthread_once()的時候,在子進程中導致死鎖。

而且,你不能在回調函數中throw一個C++ Exception(參見下面的C++ Exception支持).

當前pthread_once()實現缺少必要的多核安全雙重檢查鎖定(屏蔽讀寫操作)

 

線程本地數據:
線程本地存儲區僅爲每個進程提供了略小於64pthread_key_t對象,在實現上,提供了64個實時slot, 而且自己使用了大約5(實際數量依賴於實現)。(比如,兩個slotC庫預先分配,以啓動Android OpenGL子系統加速)。
注意,Posix要求至少128slot,但是我們不打算與Posix兼容。

除了主線城,在堆棧頂部也存儲了TLS區,詳細資料請參考bionic/libc/bionic/pthread.c文件中的註釋部分。

 

當前,使用__thread關鍵詞來定義線程本地存儲區,還不被Bionic C庫和動態鏈接器支持。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章