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版本只能运行在x86android设备上。我们并没有声明说,你能够在普通 x86 linux发布版上使用Bionic,(尽管这会很,因此欢迎大家做这样的补丁程序);

Syscall stub

每个系统调用函数都由一个小的汇编代码段实现(称为syscall stub),这是由tools/gensyscalls.py工具自动生成的,它从SYSCALL.TXT中取得输入参数。

SYSCALLS.TXT包含了一份要生成的系统调用块列表,和相应的系统调用数字标识符(ARM和X86不一样),以及它的签署。

如果你要修改这个文件,你可能要使用tools/checksyscalls.py工具,检查它里面是否包含官方linux核心头文件,如果有不合法的syscall ids,它会报告错误。

有时,C库函数其实就是一个包装,它内部调用相应的syscall名称,例如,exit函数由C库提供,它调用了_exit()这个syscall stub.

详细内容请参考SYSCALLS.TXT文件。

time_t:

time_t在32位CPU内核上定义为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()实现缺少必要的多核安全双重检查锁定(屏蔽读写操作)

线程本地数据:
线程本地存储区仅为每个进程提供了略小于64个pthread_key_t对象,在实现上,提供了64个实时slot, 而且自己使用了大约5个(实际数量依赖于实现)。(比如,两个slot由C库预先分配,以启动Android OpenGL子系统加速)。
注意,Posix要求至少128个slot,但是我们不打算与Posix兼容。

除了主线城,在堆栈顶部也存储了TLS区,详细资料请参考bionic/libc/bionic/pthread.c文件中的注释部分。

当前,使用__thread关键词来定义线程本地存储区,还不被Bionic C库和动态链接器支持。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值