1.本地层基础部分结构
Android软件系统中作为本地基础部分使用的,主要具有以下部分:
(1)C语言基础库:提供标准C库功能
(2)C语言工具库:Android特定的C语言工具
(3)init可执行程序:作为用户空间的第一个进程
(4)shell工具:提供用户调试功能
其中后三者均在Android源代码的system/core目录中,此目录也就是Android系统中最底层的部分,包括基本的启动、操作和调试等。
2. C语言基础:Bionic
Bionic提供C语言基础库的功能,Bionic的源码和头文件在bionic/目录中。
相对于传统的C库实现,Bionic的体积和内存占用量更小。Bionic支持标准C和C++库的绝大部分功能,支持数学库及NPTL线程库。
Bionic提供的C++的支持是一种最轻量级的支持,只支持了C++语法,没有支持STL标准模板库。
Bionic使用共享内存的方式来实现。
2.1 Bionic各个部分的结构
Bionic目录当中的各个子目录中的内容如下所示:
(1)libc:C库,生成动态库libc.so和静态库libc.a
(2)libm:数学库,生成动态库libm.so和静态库libm.a
(3)libdl:动态库使用工具,生成动态库libdl.so
(4)libstdc++:C++库,生成动态库libstdc++.so和静态库libstdc++.a
(5)libthread_db:线程库,生成动态库libthread_db.so和静态库libthread_db.a
2.2 Bionic的头文件
作为C库功能的实现,Bionic的头文件包括几个部分,C语言标准头文件、UNIX标准头文件、Linux内核中的头文件、Bionic特殊的头文件。
(1)主要头文件
libc/include目录中的各个文件为C语言主要的头文件,例如stdio.h、stdlib.h等。它们都是C语言标准的头文件。
libc/include/sys目录中的各个文件是Linux系统(以sys为开头)的头文件,例如time.h、ioctl.h等。
(2)Linux特定的头文件
Bionic中的libc/kernel为Linux内核头文件目录。这个目录是对Linux源代码中各个部分头文件的重新组织。
在Android的本地开发过程中,如果使用<linux/XXX.h>等方式包含头文件,引用的是这里的头文件。
例如: #include <linux/input.h> 此时实际上引用的是Bionic中libc/kernel/common/linux目录中的input.h。
2.3 属性系统的支持
Android的C库除了提供标准的功能之外,还提供了Android的属性系统的底层支持。属性的本质是一块共享内存。
Android中属性名称最大32字节,属性值92字节。
3. C语言底层库
在基础的C库之上,Android最底层的本地库是Log库和C语言工具库。
Log库头文件:主要为system/core/include/cutils目录中的log.h,logd.h等头文件,另一个相关的头文件是system/core/include/android目录中的log.h。
Log库文件路径:system/core/liblog
Log库编译的结果:目标机的动态库liblog.so和静态库liblog.a
log.h是Log库的头文件,其中包含了宏定义,主要包括LOGV、LOGD、LOGI、等宏作为Log输出的方法。
4. 设备管理功能
对于Android系统,需要一个处理设备管理的程序,它的功能类似Linux桌面系统中的udev。它通过监听Socket获得内核传递上来的信息,然后可以在用户空间中自动建立或者删除设备节点(通常是/dev/目录中的文件)。
在Android的新版中,使用ueventd程序作为设备管理的程序,ueventd使用ueventd.rc脚本作为设备列表。
ueventd程序将打开ueventd脚本,作为其中设备管理的列表。与init.rc类似,ueventd实际上也有两个,一个是名称为ueventd.rc的主设备脚本,另一个是名称为ueventd.<设备>.rc具体硬件的脚本。二者的功能和语法也是相同的。
ueventd脚本的默认路径:system/core/rootdir/ueventd.rc。
5. Shell工具
Android中的shell功能由sh(shell)和toolbox(工具箱)两个部分组成,它们是两个可执行程序,其中sh程序提供的是控制台,toolbox提供的是各个可执行程序的命令(如ls、mv等)。
6. Android属性和套接字机制
Android属性和套接字机制作为两种Android中特殊的程序交互手段。
6.1 属性机制
属性的本质是一块共享内存,每个属性使用一个键和键值的对来表示,二者的格式都是字符串。
属性的操作包括读、写两个部分。Android系统各个部分的程序中都提供了接口对属性进行操作。
本地程序中,通过libctuils中的properties.h头文件中定义的property_get()、property_set()和property_list()函数对属性进行读取、设置和列出操作。
在Java程序中,通过android.os包中的SystemProperties类的get()、getXXX()、set()等几个静态方法对属性进行读取和设置。
在命令行中,可以通过toolbox的getprop和setprop两个命令对属性执行获得、设置,以及列出所有属性等操作。
6.2 套接字机制
Android中用于通信的套接字本质上是基于Linux的套接字。其中较为特殊的地方是Android保留域名称的几个Socket。
套接字被访问时,类似于一个文件。因此,相比属性系统有限的字符信息,套接字在提供交互信息的容量没有限制。
Android特定名称的套接字本质上是文件的套接字,Android在文件系统的固定位置建立节点,赋予其全局的名称,就可以让程序的各个部分都通过名字来访问。