杨 程,黄俊伟,周俊扬,杨 倩
(1.重庆重邮信科股份有限公司应用部,重庆 400065;2.重庆理工大学电子信息与自动化学院 重庆 400054)
QT 作为一款跨平台的C++图形用户界面应用程序开发框架,致力于发展跨平台GUI 领域,以其优良的跨平台性、丰富的API和高程度的模块化开始在行业终端中展现出不平凡的实力。
Android 日志系统(Android Logging System)是一套系统级的、多功能的日志系统,它完整地记录Android 智能系统从应用层、框架层及其硬件抽象层等所有日志信息,同时Android 日志系统提供串口输出功能,用户可以将日志信息通过USB 传输至PC 端,再通过PC 端的调试工具呈现出来。
目前,在工程项目中,包括QT 在内的多种应用框架,由于没有一套完善的系统调试解决方案,大部分的应用开发都被局限于模拟器调试,而无法在设备上进行实时跟踪调试,传统的日志保存方法无法提供足够的实时性且开发调试效率慢。
为了解决这一问题,本文提出了Android 日志系统跨平台移植方案。不仅可以使QT 设备并且其他任意嵌入式Linux 设备都可以正常使用Android 日志系统,本文以智能终端行业中最流行的两种智能终端系统为研究对象,分析Android 日志系统的整体架构,并在QT 架构上进行功能性移植,具有更好的代表性和实用价值。
Android是Google 开发的基于Linux 平台的开源手机操作系统,该平台由操作系统、中间件、用户界面和应用软件组成,被誉为第一个完整、开放而且免费的一种平台[1]。截止2013 年初,基于Android 操作系统的智能手机占据全球市场份额的80%,中国市场占有率90%以上。
QT是一个跨平台的C++ 图形用户界面库,由挪威TrollTech 公司出品,目前包括QT,基于Framebuffer的QT Embedded,快速开发工具QT Designer,国际化工具QT Linguist 等部分QT 支持所有Unix 系统,当然也包括Linux,还支持WinNT/Win2k,Win95/98 平台。使用QT 您只需一次性开发应用程序,无须重新编写源代码,便可跨不同桌面和嵌入式操作系统部署这些应用程序[2]。
图1 Android 日志系统整体架构图
Android 日志系统,主要分为两个大的部分,一部分为Device 或Emulator 部分,第二部分为PC 部分。Device 端,主要完成保存全部的日志信息(Log)至内核(Kernel)空间,并将其缓存在四个不同的循环缓冲区(Circular Buffer)中;开启ADBD 守护进程,等待与PC 端进行信息交互。PC 端,根据不同用户的不同需求,通过USB 获取到Device 端缓存的日志信息,Client 可以使用ADB 命令行,也可以使用DDMS 等开发调试工具。
2.1.1 Android 日志开发接口
Android 日志信息中总共定义了5 种不同级别的输出,系统根据LOG的等级判断是否需要输出相应Log 信息,在IDE 中分别以不同的颜色,以便用户能够更精准地进行查找。
2.1.2 Android Debug Bridge
(1)ADB 介绍
Android Debug Bridge是一种多功能的命令行工具,实现用户与Android 智能手机或模拟器之间的通信功能,ADB 主要由客户端、服务端和守护进程三部分组成。
(2)ADB 功能简介
· 管理模拟器或设备状态
· 在设备或模拟器上执行命令
· 管理模拟器或设备上的端口信息
· 同步设备或模拟器上的文件信息
图2 Android Log 设备端数据流程图
Android 系统将日志信息分为四种不同的类型,分别为系统、RIL、音频、以及主要信息。因此在Logger 驱动中,首先在初始化的过程中会生成4个MISC 文件,分别保存system、radio、main、event,每个MISC 文件中包含一个循环缓冲数据流(Circular Buffer),其内容大小都为256 k,由于Android 日志系统记录整个系统的日志信息,所以处于系统启动流程中的优先启动对象(详见3.1.1)。然后用户根据需求对4个MISC 文件进行读写操作,在设备端通常是写操作,通过open打开指定类型文件节点,通过writev,readv 对设备文件信息进行读取操作。
3.1.1 Android 启动流程
图3 Android 启动流程图
Android 启动流程主要包含:硬件上电、内核启动、INIT启动。当Android 完成INIT 过程后,根据init.rc和init_XXX.rc(指定设备INIT 配置信息)文件,开启指定的后台服务进程(Background Service Program),启动Zygote 程序,再由Zygote 程序逐步启动Android 上层GUI(Graphical User Interface)和应用程序。
3.1.2 Android INIT 介绍
INIT是Linux 系统操作中不可缺少的程序之一,它是一个由内核启动的自动启动的用户级进程,进程编号始终为1[2]。Android INIT 主要完成的功能如下所示[3]:
(1)初始化日志系统;
(2)解析init.rc和init.XXX.rc 文件;
(3)设备初始化;
(4)初始化属性服务器;
(5)开启属性服务;
(6)进入一个无限循环。
移植Android 日志系统方案设计主要可以分为两个部分:QT 启动流程设计;QT 日志函数设计。
3.2.1 QT 启动流程设计
使用Android 日志系统,首先需要完成Android 日志系统的初始化流程,完成文件设备节点的注册;其次为了解决Android 日志系统保存日志信息不完整的问题,需要在QT的启动过程中添加日志信息自动保存的守护进程,方便后续项目开发调试时进行查看;最后,启动QT 平台下的第一个应用程序。
3.2.2 QT 日志函数设计
由于原生QT 日志输入将定向为标准输出流或标准错误输入流中,我们需要修改QT 输出日志的函数实现,将日志内容重定向到Android Logger 注册的4个不同的MISC 文件节点中,完成Android 日志系统在QT 平台上的移植。
图4 传统QT 启动流程
传统基于Linux的QT 设备在内核启动完成后,将直接通过init 程序进入QT的应用处理流程。
图5 移植后的QT 启动流程
移植Android 日志系统首先需要有Android 系统的初始环境,所以需要移植Android的Init 程序,在完成日志系统的初始化后,通过Service 服务程序开启ADBD 守护进程,用于与远端ADB 进行信息交互,然后可以根据设备性能选择性移植部分Service 程序,如Logcatd 进程,可以将所有的日志性能都保存在指定的路径下,由于Android 保存日志信息的循环缓冲流只能保存256 k 数据,超时的数据将被丢弃,使用Logcatd 进行完整信息保存,不论是在实时的调试或是离线调试都可很方便快捷地查看完整日志信息。最后启动QT应用。
在移植Android 日志系统的过程中,为了实现QT 日志信息与Android Logger的交互,需要将数据信息直接写入到Logger的MISC 文件中,由2.2 章节可知,在Logger 存在4个不同的MISC 文件,我们现在只使用其中的main的MISC 文件,但可以根据修改,使用不同的MISC 文件,进行分别保存。代码实现细节如下:
步骤一:在QT应用中加入测试LOG 信息;
步骤二:设备上运行QT 程序,通过ADB 截取LOG;
步骤三:观察LOG 内容及时间。
测试完成,验证成功。
本文通过对Android 日志系统从架构和流程上做出深入剖析,提出一种新型的、跨平台的系统调试解决方案设计,并成功在以QT为架构的工程实现中得到验证。本设计方案在未来将不仅限于QT,应用空间潜力巨大。除Android 日志系统外,其还拥有很多可以被其他平台吸取的优点,比如在通信业务方面的RIL 框架设计,独立硬件设备的硬件抽象层的理念。如何更好地吸收这些开发资源的优点,运用于我们自身所需要的地方,将成为继续研究的方向。
[1]韩超,梁泉.Android 系统原理及开发要点详解[M].北京:电子工业出版社,2010:10.
[2]闫效莺.基于嵌入式Linux 软件平台技术的研究[D].西安:西北大学,2006:45.
[3]李凯.Android 操作系统分析与移植[D].广州:华南理工大学,2011:37.