310 likes | 660 Views
Android 嵌入式系统软件开发. Android Embedded System Software Development 周 庆 国 ( zhouqg@lzu.edu.cn ) 兰 州 大 学. 第三章 Android 系统相关工具及环境库. 3.1. 3.2. 3.3. 3.4. 3.5. 3.6. 3.7. 系统底层库和程序的结构. 文件系统介绍. shell 和 toolbox 工具介绍. C 语言底层库 libcutils. C++ 工具库 libutils. busybox 移植介绍. init 进程.
E N D
Android嵌入式系统软件开发 Android Embedded System Software Development 周 庆 国 (zhouqg@lzu.edu.cn) 兰 州 大 学
第三章Android系统相关工具及环境库 3.1 3.2 3.3 3.4 3.5 3.6 3.7 系统底层库和程序的结构 文件系统介绍 shell和toolbox工具介绍 C语言底层库libcutils C++工具库libutils busybox移植介绍 init进程
3.1 底层库和程序的结构 返回首页 Android的本地实现层次具有基本的库和程序,是Android基本系统运行的基础,主要包含: (1)标准C/C++库Bionic (2)C语言工具库libcutils (3)init进程 (4)shell工具 (5)C++工具库libutils 3
3.2 Android文件系统介绍 Android文件系统的结构 Android源码编译后得到system.img,ramdisk.img,userdata.img(采用cpio打包、gzip压缩)映像文件。 其中,ramdisk.img是整个文件系统, system.img包括了主要的包、库等文件,userdata.img包括了一些用户数据。 平台加载这三个映像文件后,会把 system和 userdata分别加载到 ramdisk文件系统中的system和 userdata目录下。 4
文件系统介绍 5
文件系统介绍 cache : 缓存临时文件夹,除了T-mobile的 OTA更新外,别无用处 mnt :SD卡中的FAT32文件系统挂载的目录 etc : 指向 /system/etc ,配置文件存放目录 system :Android根文件系统中一个很重要 的目录,系统中的大部分东西都在这里了 6
文件系统介绍 sys :用于挂载 sysfs文件系统。 在设备模型中,sysfs文件系统用来表示设备的结构。将设备的层次结构形象的反应到用户空间中。用户空间可以修改sysfs中的文件属性来修改设备的属性值 。 sbin : 存放用于调试的adbd程序等系统管理工具 proc :/proc 文件系统下的多种文件提供的系统信息不是针对某个特定进程的,而是能够在整个系统范围的上下文中使用 data :存放用户安装的软件 以及各种数据 root :暂无内容 dev :设备节点文件目录 7
分离Android文件系统 • system.img,ramdisk.img,userdata.img映像文件是采用cpio打包、gzip压缩的,可以通过file命令验证: • file ramdisk.img • 输出: ramdisk.img: gzip compressed data, from Unix, last modified: Wed Mar 18 18:16:10 2011 8
分离Android文件系统 Android源码编译后除了生成system.img,userdata.img之外还生成system和 userdata文件夹,因此不需要解压它们。 Android源码编译后还生成root文件夹,其实root下的文件与 ramdisk.img 里的文件是一样的,不过这里还是介绍怎样把 ramdisk.img解压出来: 将ramdisk.img复制一份到任何其他目录下,将其名称改为ramdisk.img.gz,并使用命令 gunzip ramdisk.img.gz 9
分离Android文件系统 返回首页 • 然后新建一个文件夹,叫ramdisk,进入,输入命令 cpio -i -F ../ramdisk.img • 这下,你就能看见并操作ramdisk里面的内容了。 • 然后把Android源码编译后生成的system和 userdata里的文件复制到 ramdisk/system和 ramdisk/userdata下。这样就得到一个文件系统了。 10
3.3 shell和toolbox工具 返回首页 Init.rc脚本: service console /system/bin/sh console 代码:system/core/sh 代码位于:system/core/toolbox 。 编译后路径: /system/bin/toolbox 命令符号将连接到toolbox可执行程序上。 命令源文件: int {xxx}_main(int argc,char **argv){ } 增加新命令,需在Android.mk中加入命令的相应名称。 11
3.4 C语言底层库libcutils 返回首页 头文件:system/core/include/cutils 源文件:system/core/libcutils 编译结果:libcutils.so 主要头文件: threads.h :线程 sockets.h ::Android 的套接字 properties.h : Android 的属性 log.h ::log 信息 array.h :数组 ashmem.h :匿名共享内存 atomic.h :原子操作 mq.h :消息队列 12
3.5 C++工具库libutils 头文件:frameworks/base/include/utils 源文件:frameworks/base/libs/cutils 编译结果:libutils.so 该库分成两个部分: (1)底层的工具 (2)实现主要为实现IPC(进程间通讯)的Binder机制 13
C++工具库libutils 公共库部分主要包含的头文件如下所示: Errors.h:定义宏表示错误代码Endian.h:定义表示大小端的宏misc.h:几个字符串和文件相关的功能函数TextOutput.h:定义文本输出的基类TextOutputBufferedTextOutput.h:类BufferedTextOutput,它是一个TextOutput的实现Pipe.h:定义管道类PipeBuffer.h:定义内存缓冲区域的类BufferList.h:定义链表的模版类SharedBuffer.h:定义类SharedBuffer表示共享内存。String16.h:定义表示双字节字符串的类String16String8.h:定义表示单字节字符串的类String8,并包含了从String16转换功能 14
C++工具库libutils VectorImpl.h:定义表示向量的类VectorImplVector.h:定义继承VectorImpl的类模版Vector,以及排序向量类SortedVectorImplSortedVector.h:定义排序向量的模版SortedVectorKeyedVector.h:定义使用关键字的向量模板KeyedVectorthreads.h:定义线程相关的类,包括线程Thread、互斥量Mutex、条件变量Condition、读写锁ReadWriteLock等socket.h:定义套结字相关的类SocketTimers.h:定义时间相关的函数和定时器类DurationTimer ZipEntry.h、ZipFileCRO.h、ZipFile.h、ZipFileRO.h、ZipUtils.h:与zip功能相关的类。 15
C++工具库libutils Binder进程间通讯部分 RefBase.h:引用计数,定义类RefBase。Parcel.h:为在IPC中传输的数据定义容器,定义类ParcelIBinder.h:Binder对象的抽象接口, 定义类IBinderBinder.h:Binder对象的基本功能, 定义类Binder和BpRefBaseBpBinder.h:BpBinder的功能,定义类BpBinderIInterface.h:为抽象经过Binder的接口定义通用类,定义类IInterface,类模板BnInterface,类模板BpInterfaceProcessState.h:表示进程状态的类,定义类ProcessStateIPCThreadState.h:表示IPC线程的状态,定义类IPCThreadState IServiceManager.h:表示服务管理器的类,供其它需要构造服务的类使用IPermissionController.h:权限控制类。 16
C++工具库libutils 返回首页 几个与内存相关的类的头文件如下所示:IMemory.h:定义内存相关类的接口,表示堆内存的类IMemoryHeap和BnMemoryHeap,表示一般内存的类IMemory和BnMemory。MemoryHeapBase.h:定义类MemoryHeapBase,继承并实现BnMemoryHeapMemoryBase.h:定义类MemoryBase,继承并实现BnMemory在一般的使用过程中,通常是以使用MemoryHeapBase类分配一块堆内存(类似malloc),而MemoryBase表示从一块分配好堆内存中的一部分内存。此外内存相关的功能中还包含了头文件MemoryDealer.h和MemoryHeapPmem.h。 17
3.6 busybox移植介绍 (1)在Android SHELL 中无法使用命令自动补全功能,同时,使用上下键无法翻转和查看之前相关的历史命令。 (2)也没提供诸如find、grep等一些较高级的功能命令。 18
busybox移植介绍 Google没有使用传统的标准的glibc来作为C库使用,而是自己重新开发了bionic来作为其Android上的C库使用。 同时,Google官方公布的Toolchain工具链也只是基于bionic C库而开发的。 网上多数有关Android busybox方面的移植内容一般都是基于CODESOURCERY的交叉编译工具链来完成相应的编译开发工作的,通常来说这钟方式不太合理的 19
busybox移植介绍 基于静态链接编译的busybox中的命令有些在Android上是无法使用或者是可以使用但其功能并不完全,比如:ping命令等。介于基于Android bionic C库比传统标准的glibc存在的优点,对busybox的移植策略并不像网上大多数网友那样静态地链接到(基于)传统的标准的glibc库上,而是基于Android自身的bionic C库和Toolchain交叉编译工具链而来的。 20
busybox移植介绍 基于CM的busybox源代码移植工作。 (1)首先,下载CM 的busybox源代码,同时,解压进Android源代码的external/busybox目录中。 (2)添加stdio.h头文件到external/busybox目录中的下列文件之中: coreutile/df.c 、util-linux/mount.c 、util-linux/umount.c 21
busybox移植介绍 (3)如果是froyo之前的版本,需在bionic/libc/include/sys/resource.h中添加下列定义语句:typedef unsigned long rlim_t; (4)在Android.mk中设置CYANOGEN_BIONIC变量开关的值CYANOGEN_BIONIC:=true (5)编译busybox derek@derek-ThinkPad-Edge: ~/Android/wholeplatform/froyo_blcr$ make –j4 busybox 22
busybox移植介绍 # mount -o remount,rw /dev/block/mtdblock0 /system # cat /sdcard/busybox > /system/xbin/busybox # mount -o remount,ro /dev/block/mtdblock0 /system # cd system/xbin # chmod 755 busybox # busybox sh # busybox ls -lh system/xbin/busybox -rwxr-xr-x 1 root root 401.4K Jul 8 21:23 busybox 23
busybox移植介绍 返回首页 编译移植过程,可知基于bionic C库动态移植编译的busybox(约400K)比基于bionic C库静态链接编译(约800K)和基于glibc静态链接编译的busybox(约1.8M)都要小的很多,这对于我们从事嵌入式系统开发来说是比较可观的。 24
3.7 Init进程 Init是Linux内核启动后的第一个真正意义上的用户空间程序,以守护进程的形式存在运行。 Init的相关内容位于Android源代码树system/core/init/目录中。 Init的初始化脚本语言可以参考Android源代码树system/core/init/readme.txt文件中的相关描述,而脚本中关键字的定义可以参考Android源代码树system/core/init/keywords.h文件中的相关描述。 25
Init进程 在某些情况下,当我们为了调试或获得其他程序的一些相关信息,我们可以利用Android系统中自带的logwrapper程序来执行其他一些程序。这样就可以将错误或其他输出信息重定向到Android的Log系统中(即之后可以使用Logcat进行访问)。比如: service rild /system/bin/logwrapper /system/bin/rild 26
Init进程 当平台启动时,kernel中的引导参数将会被设置为init=/init,从而当挂载文件系统成功后便会开始执行Init初始化程序。因此,需要分析Init初始化程序的执行流程,才能了解Init进程的行为。Init的入口点位于源代码树system/core/init/init.c的main函数中。 27
Init进程 注册SIGCHILD子进程信号 umask进行重新归零 创建所需的基础文件系统/dev、/dev/pts(对应devpts)、/dev/socket、/proc(对应proc)、/sys(对应sysfs) 创建并打开虚拟的空设备/dev/null和/dev/kmsg 初始化Log日志系统 读取并解析init.rc 导入kernel命令行和ramdisk属性文件 获取相关的硬件名称信息 获取 init.<machine_name>.rc硬件相关的初始化脚本配置文件,并进行读取解析 28
Init进程 遍历执行early-init的活动 设备初始化,sys目录,在/dev自动创建设备节点 属性进行初始化工作 ro.debuggable为真,则为keychord打开监听 开启控制台 解析initlogo.rle,在终端显示Android文本 导入kernel命令行参数,对系统属性进行相关的参数设置 遍历相关链表,执行带有init标志的活动 解析所有任何在system和data目录中的属性文件 建立SIGCHILD子进程信号处理机制 确认是否拥有了所需的所有管道(描述符) 29
Init进程 遍历执行带有early-boot标志的活动 遍历执行带有boot标志的活动 运行属性触发器 使能属性触发器标志 添加管道device_fd、property_set_fd和signal_recv_fd、keychord_fd的轮询事件 如果支持、打开了BOOTCHART可视化分析,则需要相应地启动该分析功能 进入初始化进程的无限循环体,主要操作包括:重新复位revents接受状态、遍历执行Action队列、重新启动相关的必要的服务进程、轮询上述添加的管道(描述符),并调用相应的处理函数来完成执行流程 30
谢谢 31