1. 什么是Bionic
Bionic是Android平台为C/C++开发者进行原生应用程序开发所提供的符合POSIX(可移植操作系统接口)标准的C库。
是Android操作系统BSD(UNIX操作系统中的一个分支)标准C库的衍生库。
Bionic提供了在Android平台上开发任何类型的功能性原生代码所需的最小构造集。
通俗地讲,Bionic(Bionic的头文件集)就是NDK的API
Bionic C库头文件在 %NDK_HOME%\platforms\android-<api-level>\arch-<architecture>\usr\include内
其他的C标准库
只要是符合ANSI(美国国家标准学会) C标准的C库都可以叫做标准C库。
POSIX标准的C库是在ANSI标准的C库的基础上增加一些附加结构。
现有的著名的POSIX标准的C库有:GUN C库(glibc)和Embedded Linux C库(uClibc)。
注意,Bionic C库不以任何方式与其他标准C库二进制兼容,这意味着基于其他C库生成的二进制文件不应该与Bionic进行动态链接。
注意,虽然Android只提供Bionic C库,但是基于其他符合POSIX标准C库生成的应用,无可争议地可以在Android上面运行(因为Android本身是支持POSIX标准的)。
2. 为什么要Bionic?
google自己搞的bionic libc来替代glibc想来是有原因的,本来glibc也是lgpl,应该也没有版权问题,但是系统调用的接口有限,google应该是用自己的bionic libc来暴露出更多的系统调用接口,系统调用不属于GPL,这样才有可能让上层有更大的权限去操作底层驱动,这样硬件厂商就可以将有关商业利益的代码放到HAL层(hardware abstraction layer),底层驱动层只要提供操作接口,这种代码在内核公开出来也无所谓,主要的业务逻辑仍然在HAL层以二进制或者库的形式存在,虽然放到了用户空间,但这才是正真的驱动,也正好避开了GPL的感染性,其实主要是显示先关的芯片有这个需求。
3. Bionic的核心思想:简单化5. Bionic主要内容即C库应该只提供对内核功能的轻量级封装,不应该过于智能化,考虑太多的边界条件。
Bionic这个词表明它一部分来自BSD,一部分来自Linux。它的源码主要由BSD C库的代码片段和自定义的linux代码(用于处理线程,进程,信号,和其他事情)混合而成。所有原始的BSD块,遵循BSD版权声明。特定的Bionic部分遵循Android open source project版权声明。
一切发行版都遵循BSd版权
4. 架构
Bionic目前支持x86和arm指令集。理论上讲,可以支持更多的架构,不过需要做一些工作。比如,向SYSCALLS.TXT文件中添加系统调用IDS,如下面所述,或者修改动态链接器)。
ARM相关代码在arch-arm/下面,x86相关代码在arch-x86下面。
注意,x86版本只能运行在x86android设备上。我们并没有声明说,你能够在普通 x86 linux发布版上使用Bionic,(尽管这会很”酷”,因此欢
迎大家做这样的补丁程序);
Bionic提供了:C标准库宏、类型定义、函数,以及少数Android特有特性。
从功能角度Bionic提供了:
内存管理
文件输入/出
字符串操作
数学
日期和时间
进程控制
信号处理
网络套接字
多线程
用户和组
系统配置
命名服务切换
1)Syscall stub
每个系统调用函数都是用一段小型汇编码(即 syscall stub)实现的,这些 syscall stub 是由 tools/gensyscall.py 通过读取 SYSCALL.html 生成的。
SYSCALL.html 包含要生成的 syscall stub ,相应的系统调用号(x86与arm不同),及相应的签名。
如果你想修改SYSCALL.html,可以利用 tools/checksyscalls.py 来比较SYSCALL.html 和 Linux内核头文件。当发现无效的系统调用号时,就会报告错误。
2)time_t 和 off_t
在32位CPU上,Linux内核定义 time_t 为 32位。但是将 time_t 定义为 64位或许更好,因为可以解决 bug Y2038。但是Linux内核维护人员Y2038不紧急,所以time_t依然是32位。
但是,Bionic提供了time64.h 这个头文件,定义了 time64_t 类型,和相应的函数 mktime64()、localtime64() 等。
off_t 也是 32 位的,Bionic中定义了 loff_t 类型(64位),从而做到兼容BSD, 它被typedef 为 off64_t,兼容Linux。
3)时区管理
当前时区的名字取自 TZ 环境变量(如果定义了 TZ 变量)。
如果没有定义 TZ 环境变量,则检查名为 persist.sys.timezone 的系统属性。
时区信息数据库和索引文件位于 /system/usr/share/zoneinfo, 而不是 /usr/share/zoneinfo(POSIX规范定义的)