一种基于非虚拟化体系架构的Android运行环境实现方法与流程

文档序号:15850296发布日期:2018-11-07 09:45阅读:667来源:国知局
一种基于非虚拟化体系架构的Android运行环境实现方法与流程

本发明属于计算机基础软件领域,涉及一种基于非虚拟化体系架构的android运行环境实现方法。

背景技术

据statcounter统计,android在2017年3月份超过了微软的windows,成为互联网上最流行的操作系统;移动互联网的快速发展也使移动应用无论从数量还是流量都已经大大超过了桌面应用,从各大电商平台移动应用下单量已远超桌面应用这一现状可以看出这一端倪;手机游戏的火爆效应促使大量游戏玩家已不再满足手机小屏幕和低性能限制,迫切希望手机游戏能够高性能运行在桌面终端。

若能够实现android应用在国产操作系统平台上顺畅运行,借力android开发生态和应用生态,将使国产操作系统具备庞大的开发者群体、易用强大的开发工具、丰富的开发组件、标准的开发接口和完善的开发资料等核心优势。但是,在现有国产linux桌面开发生态的基础上,完善已有开发工具、组件、资料等工作量巨大,尤其是开发人才稀缺,难以支撑为国产操作系统建立完善的开发生态。

目前国内外相关研发有三个方向,一是虚拟机模拟技术,基于桌面操作系统实现安卓系统虚拟运行环境,支持安卓应用运行;二是android-x86技术,对安卓系统进行扩展,使其支持pc,即实现安卓系统的x86定制与适配;三是chrome/arc浏览器技术,为安卓应用提供基于chrome浏览器的虚拟运行环境。

1、虚拟机技术

安卓模拟器是典型的虚拟机技术,其发展壮大在一定程度上得益于手机游戏的蓬勃发展,一些用户不满足于手机屏幕以及内存等硬件限制,需要更好的游戏体验,就催生了将手机游戏移植到pc上的需求。目前市场上安卓模拟器软件种类繁多,但技术源头上主要有两大流派:bluestacks和virutalbox,国内的安卓模拟器也大部分基于这两种技术开发实现。bluestacks的原理是把android底层api接口翻译成windowsapi,对pc硬件本身没有要求,在硬件兼容性方面有一定的优势。virtualbox的原理是在windows内核底层直接插入驱动模块,依托cpu对虚拟化的硬件支持,创建一个完整虚拟的电脑环境运行安卓系统。

虚拟机技术存在如下问题:一是安卓模拟器的出现与游戏关系密切,虽然能够支持安卓应用运行,但开发的重点是为了满足游戏用户需求,而不是通用安卓应用与开发需求;二是受制于用户游戏环境,主要支持windows和mac平台,不支持linux平台,更不支持国产操作系统;三是依赖于cpu的硬件虚拟化技术,当前国产cpu(飞腾、龙芯等)的技术状态无法支持;四是引入虚拟机后,资源消耗大,卡顿、延迟、偶发系统性奔溃、不流畅。

2、android-x86技术

有了在pc上借助android模拟器运行安卓应用的想法,就有用户提出直接在pc上运行android应用的思路。在2009年,yisun开始了将android移植到x86-pc上的尝试,并基于android1.6推出了android-x861.6,后来持续跟随android的发展步伐,目前已发展到androidx867.x。androidx86系统的定位是x86-pc的bsp(boardsupportpackage),并在androidx86的基础上扩展android框架,基于android为桌面pc提供不同于常规的操作使用环境。2013年,tieto公司实现了基于android4.2/4.4的类似windows的多窗口。至此,将android发展成一种面向x86的桌面操作系统,我们统称为android-x86,国内知名产品包括remixos、phoenixos和emindos(openthos)均基于此技术实现。

android-x86技术如下问题:一是从技术上看,当前的androidx86、remixos、phoenixos、emindos/opnenthos应该都属于基于aosp的有限扩展实现,我们统称为android-x86技术体系,它们虽不是一个全新的操作系统,但相比较已经具有一定基础的国产操作系统而言,是一条自顶向下的新路径,也意味着原先基于国产操作系统的研制开发工作和linux应用系统全部抛弃,需要从头再来,因为这些系统基本不支持linux应用,这是不可取的。虽然基于容器(container)技术可以实现android开发环境到android-x86技术平台的移植,支持在其平台上开发android应用,也支持部分linux应用的运行,但要完成基于国产操作系统实现的linux应用的全部迁移,在技术道路上风险巨大,存在诸多不确定技术因素,且系统性能大受影响。二是从生态建设上看,android-x86技术体系产品都要面临原先国产操作系统开始遇到的与硬件厂商适配的难题,从这些产品在市场运行反馈的问题就可以看出,绝大多数归属于硬件和软件库的适配兼容问题,产品开发者绝大多数时间拖沉在这种适配开发修改工作中,这意味着这些产品还要把国产操作系统从前走过的路再走一遍。三是从外在因素上看,google虽没有把android扩展到桌面,并不是没有这个技术实力(其实android6.x已经有平铺式多窗口探索性的技术支持,在android7.x已进一步有堆叠式多窗口的支持),之所以没有这么做,是出于其战略考量,一旦chrome/arc成熟,势必会阻碍android桌面化的发展进程,可以说android与chrome/arc是google打造移动计算和物联网生态的两把利器,两者只能互相促进,不能互相阻滞。

3、chrome/arc技术

chrome/arc技术的出现与发展,是google利用android生态环境打造其另外一个产品chromeos生态环境的一步举措。windows10自发布以来,在一定程度上影响了google的chromeos生态布局。因此,google决定要实现把自己的生态圈零成本地“侵入”到其它的平台,特别是桌面平台。chrome浏览器已经实现跨平台支持,它的一些独特特性(支持nacl,nativeclient)使其不仅仅是一个浏览器,更像是一个运行平台。但从cws(chromewebstore谷歌在线应用商店)的应用可以看出,目前基于nacl的应用很少,这个尴尬的状况制约了chromeos的发展。google就开始有计划地开始借用android生态来完善chromeos,即让chrome支持android应用无缝运行,而arc正是实现这一目标的技术方法,chromeos和android系统可以真正地融合为一。在此基础上,再推出统一标准的设计规范(materialdesign),google天下布局的计划就能以很低的成本实现,可以说arc的存在意义重大。

chrome/arc技术存在如下问题:一是chrome/arc是构建在chrome浏览器之上,必须依赖于chrome浏览器,这种技术体制决定了其性能和兼容性较差;二是chrome/arc部分开源,代码不全部掌握,这与自主可控和国产化的目标不一致。三是存在一些不确定技术因素,比如如何适配pc硬件等,这也导致其与一些pc设备不兼容。



技术实现要素:

本发明要解决的是国产操作系统与安卓应用软件不兼容的技术问题,实现国产操作系统上运行安卓应用。

为解决上述技术问题,本发明提出一种基于非虚拟化体系架构的android运行环境实现方法,在现有linux内核上构建android运行环境,记为xdroid,将android应用框架与android运行时库迁移到了标准linux内核之上。

进一步,变动的android部分包括运行支撑方面、图形加速渲染方面、设备使用方面和多媒体支持方面;

一、运行支撑方面:包括xbionic库、进程通信机制xbinder和匿名共享内存机制xashmem;

xbionic库:基于android的bionic库与linux的glibc库两者的异同创建xbionic库,两者的异同分三种情况处理:一是接口和语义一致的,xbionic库直接调用linuxglibc库;二是android独有的,xbionic库基于国产linux重新实现;三是接口一致但语义不一致的,xbionic库进行重新编写;

xbinder:在用户态实现基于请求代理模型,xbinder内部基于linux的共享内存维护了一块数据交换空间,通过增加一次数据拷贝和相应的同步机制,实现数据的一致性;

xashmem:匿名共享内存机制xashmem以系统库的形式在用户态实现与ashmem接口一致,同时在系统运行时库层和应用程序框架层均提供了访问接口;其中,在系统运行时库层提供了c/c++调用接口,在应用程序框架层提供了java调用接口,java接口通过jni方法调用c/c++接口,逐步深入到内核,最终调用到xashmem;流程上,匿名共享内存机制xashmem提供并实现三个核心操作,分别是共享设备文件创建、共享文件到进程空间映射以及对共享内存空间进行读写操作;

二、图形加速渲染方面:对android的opengles系统进行重构,提出基于opengl的硬件图形加速器,图形加速器由验证层、翻译层以及渲染器三部分组成;

三、设备使用方面:在硬件抽象层注册每个硬件对象的代理,当上层需要访问硬件的时候,就从当前注册的硬件对象代理里查找,找到之后代理会向上层的运行时库提供该硬件对象的操作接口,该操作接口就保存在上层运行时库中,上层应用或框架再通过这个操作接口来访问硬件;

代理模式架构加载的共享库不包含操作底层硬件驱动的功能,仅保存代理提供的操作接口,当代理第一次被使用时加载到内存,后续再使用时仅返回硬件对象操作接口,不会存在设备多次打开问题,且多进程访问时返回的只是函数指针;

四、多媒体支持方面:多媒体组件涵盖播放流程包括读取datasource、分路demuxer、解码decoder和输出output;

android关于读取datasource和分离demuxer代码的移植工作在国产操作系统平台上重新编译;

omxcodec通过iomx借助xbinder机制使用omx服务,omx把软编解码和硬件编解码统一看作插件的形式管理起来,omx借助omxmaster和omxnodeinstance实现一个可扩展类似插件的编解码组件应用框架;omxmaster负责omx中编解码器插件管理,软件解码和硬件解码都是使用omx标准,挂载plugins的方式来进行管理;软件解码通过addplugin挂载,硬件编解码通过addvendorplugin()加载多媒体编解码共享库;

进一步,xbionic库中android的bionic库与linux的glibc库两者接口一致但语义不一致时,xbionic库进行重新编写的内容包括:

(1)处理器构架:xbionic添加系统调用ids,或者修改动态链接器,以支持龙芯mips等国产硬件平台;

(2)系统调用:xbionic中每个系统调用函数都由一小块汇编代码实现,称为“syscallstub”,由“gensyscalls.py”脚本自动生成,从“syscalls.txt”中取得对应的参数;

(3)时间管理:android提供相应的头文件,定义一个time64_t类型和相关的函数;如果strftime()使用time64_t,“%s”格式所支持的日期应该大于等于2038;

(4)时区管理:当前时区的名字取决于tz环境变量,如果tz环境变量未定义,那么将使用linux系统名为“persist.sys.timezone”的系统属性;时区数据库和索引文件位于是在posix兼容路径“/usr/share/zoneinfo”中,而不是android系统“/system/usr/share/zoneinfo”中;

(5)关闭:即off_t,将loff_t型定义为64位变量;

(6)linux内核头文件:android自带一套经过特殊处理的linux内核头文件,允许用户空间代码使用内核特有的声明,这些头文件由一个脚本自动产生,只包含原始linux内核头文件中的公有定义;

(7)pthread实现:xbionic中pthread的实现依赖国产linux标准的pthread库实现android运行环境依赖的pthread库,同时确保与android的pthread的数据结构和语义的一致性,xbionic的pthread特征如下:

开放含有少量符号的链接器入口用于动态链接;

xbionic不支持pthread_cancel();

pthread_once()函数:在使用pthread_once()函数时不能在其回调函数中调用fork();

pthread_mutex_t和pthread_cond_t的每个类型都只有4个字节;

支持normal、recursive和error-check互斥体;

不支持进程共享互斥和条件变量;

对读写锁、互斥体的优先权和其他高级特征的支持是可选的,默认是不支持的;

(8)线程相关数据处理:即thread-specificdata,线程本地存储区仅为每个进程提供了64个pthread_key_t对象,在实现上,提供64个实时slot,而且自己使用了5个;posix标准要求至少128个slot;除了主线程,xbionic在栈顶部设置了线程局部存储区;xbionic库和动态链接器均不支持使用_thread关键词来定义线程本地存储区;

(9)多核支持:处理器必须提供相应的操作原语;

(10)访问系统属性:android向系统中所有的进程提供了一个简单共享的键值对空间以及属性的字符编码,每一个都是被限制大小的字符串,与一个被限制大小的字符串值相关联;相应的头文件既能够用于读系统属性,同时也定义键/值对的最大大小;xbionic用一块内存区域模拟了这个键值对空间;

(11)用户/组管理:xbionic将android运行环境的用户权限限制为linux当前用户的权限,以降低安全威胁;

(12)dns解析器:xbionic的dns解析器基于netbsd-derived解析库实现,与glibc相比具有以下特性:

不实现“name-server-switch”特性;

读取“/system/etc/resolv.conf”而不是“/etc/resolv.conf”;

从系统属性中读取服务列表,代码查找“net.dnsl”、“net.dns2”;每个属性包含一个dns服务器的ip地址;xbionic支持“per-process”的dns服务器列表,使用属性“net.dnsl.<pid>”、“net.dns2spid>”,<pid>代表当前进程的id号;

在执行查询时,使用随机查询id,以提高安全性;

在执行查询时,给本地客户socket绑定一个随机端门号,以提高安全性;

(13)pthread实时定时器:xbionic支持timer_create()、timer_gettime()、timer_settime()和timer_getoverrun(),也支持sigev_thread实时定时器;

(14)二进制兼容性:xbionic和xdroid在国产linux平台的实现依赖glibc,xbionic修改编译android的工具链,使其编译的程序能够进行正确处理二进制不兼容的问题;

对于不使用dlopen()/dlsym()的android应用,工具链可以直接依赖国产linux上的c库头文件通过静态链接的方式生成程序,相应的程序在国产linux上正常运行;

(15)动态链接器:xbionic没有使用linker,而是通过修改glibc的ld链接器使其能够区分引用符号的一方是来自android应用还是来自xbionic,如是前者则使用xbionic的符号,如是后者则使用glibc导出的符号;

(16)c++异常支持:xbionic通过增加以下约束部分实现对c++异常的支持:

如果在pthread_once的回调函数中抛出异常,xbionic将保持对应的pthread_once_t互斥器的锁定状态,再次调用pthread_once将导致死锁;

在xbionic的实现机制下,为xbionic提供的回调不应抛出异常;

(17)包含路径:xdroid的工具链能够自动分析xbionic的目录结构,相应地将库文件路径自动添加到c代码的包含路径中,包括libc/arch-$arch/include、libc/include或libc/kemel/arch-$arch等。

进一步,xbinder机制的实现涉及到4类角色:xbinder服务、servicemanager、server和client;

client客户进程,代表了发起请求的进程;

server服务进程,代表了响应请求的进程;

servicemanager服务管理器,servicemanager是android系统各个服务的管理者,android系统中的各个服务都是添加到servicemanager中进行管理的,而且每个服务都对应一个服务名;当client获取某个服务时,则通过服务名来从servicemanager中查找获取相应的服务;

xbinder服务,任何请求与响应,都要经过xbinder这个中介进行处理。

本发明有益效果如下:

1.非虚拟化的体系架构

xdroid无需借助虚拟化技术(包括虚拟机、模拟器或容器),而是立足桌面操作系统内核提供的基础库和基础运行机制,自底向上逐层实现android应用运行所需要的android底层运行支撑库,进而实现android运行时库的高效迁移,在桌面操作系统平台上实现了android的运行环境,与基于虚拟化的技术相比,xdroid真正实现了桌面应用与android应用生态完全融合,应用的启动速度快、性能高;同时基于不同平台实现,就容易实现跨平台运行。

2.基于opengl的android3d加速实现框架

xdroid基于国产桌面操作系统的opengl高效实现android依赖的opengles的图形加速接口,可以直接使用硬件gpu进行图形加速,可以有效支撑仿真等各类大型图形密集型应用,其图形效果远高于手机终端。

3.自底向上的层次化迁移模型

xdroid提出的自底向上的层次化的迁移模型,即迁移过程中修改以尽可能优先修改底层基础运行时库为原则,尽可能不修改android应用直接依赖的android框架,因此xdroid兼容标准的android应用接口,android应用包无需修改即可直接运行。同时,xdroid还兼容标准的开发与调试接口,可直接用android开发工具为linux开发应用。

4.异构的加载器模型

xdroid基于标准桌面操作系统的加载器重新实现了android的加载器linker,在同一进程中实现了异构运行时库的融合,这种模型可充分利用linux针对不同处理器架构和硬件平台的优化成果,显著提升性能;同时,可使linux直接兼容android可执行文件。

5.最低特权模型

xdroid在用户态重新实现了android应用运行所必须的binder和ashmem这两个内核驱动的功能接口(分别对应上述方案中的xbinder和xashmem),在确保功能一致的前提下,降低了xdroid的运行特权要求,xdroid仅需当前用户(非root)的权限即可运行,显著降低了android应用潜在的安全威胁。

附图说明

图1为基于虚拟和非虚拟化技术的体系架构对比图,左边是基于虚拟化技术的体系结构,右边是基于非虚拟化的体系架构。

图2为现有android和本发明xdroid的体系组成对比图,左侧是android的体系组成,右侧是xdroid的体系组成。

图3为本发明实施例中基于请求代理模型的进程通信机制xbinder的结构框图。

图4为本发明实施例中匿名共享内存机制xashmem的操作流程图。

图5为本发明实施例中跨平台图形加速器实现模型。

图6为本发明实施例代理模式实现架构图。

图7为本发明实施例led应用中代理模式实现架构图。

图8为本发明实施例多媒体服务应用流程图。

图9为本发明实施例omx实现框架图。

图10为本发明实施例led_module_t实现类图。

图11为本发明实施例hw_module_t与hw_module_methods_t及硬件open函数的关系图。

图12为本发明实施例led_device_t实现类图。

具体实施方式

实施例一

一种基于非虚拟化体系架构的android运行环境实现方法,在现有linux内核上构建android运行环境,记为xdroid;针对这些问题,xdroid另辟蹊径,无需借助虚拟机或模拟器,在linux上重新实现了android的核心库,将android应用框架与android运行时库迁移到了标准linux内核之上,并修改了android框架,最终实现了对android应用的支持,即android应用可以无需做任何修改即可借助xdroid直接在linux运行。如图1和图2所示,与基于虚拟化的体系结构相比,xdroid少了虚拟机/模拟器和android的linux内核两层,既摆脱了对虚拟机的依赖又可显著降低性能开销,使得运行在xdroid之上的android应用可达到与标准linux应用相近的性能。

修改的android部分包括运行支撑方面、图形加速渲染方面、设备使用方面和多媒体支持方面;

一、运行支撑方面:xbionic库、进程通信机制xbinder和匿名共享内存机制xashmem

(1)android的bionic库作为基础库,原先依赖于android的linux内核实现,因此,xdroid基于国产linux操作系统的glibc库和标准内核重新实现了bionic—xbionic;(2)android为了实现应用间的高效交互引入了匿名共享内存机制ashmem和进程间通信机制binder,android下这两种机制均是以内核驱动的形式实现的。对于android应用的正常运行而言,这两种机制必不可少,因此需要在国产linux操作系统进行移植,且不能影响其它linux应用,同时为了减少因引入驱动带来的高特权级的安全隐患,xdroid将在用户态重新构建具备这两个驱动功能的相应组件xashmem和xbinder。其中:

1、xbionic库:基于glibc和国产操作系统内核实现的xbionic

bionic是android其他运行时库和应用运行最基础的库,是操作系统内核与应用间的最核心的功能接口,至关重要,其本质就是android版的libc库。但在设计时,bionic针对嵌入式设备的特性对其进行了简化和定制,只针对内核提供轻量级的包装,让它尽可能小,而不会去处理一些非常细节的问题。所以,基于国产linux操作系统在实现时,需要统筹考虑bionic与glibc的异同点。

本发明基于android的bionic库与linux的glibc库两者的异同创建xbionic库,两者的异同分三种情况处理:一是接口和语义一致的,直接调用linuxglibc库;二是android独有的,xbionic库基于国产linux重新实现;三是接口一致但语义不一致的,xbionic库进行重新编写,重新编写的内容包括:

(1)处理器构架。android对arm和x86指令集支持较为完善,理论上可以支持更多指令集,但是xbionic需要添加系统调用ids,或者修改动态链接器,以支持龙芯mips等国产硬件平台。

(2)系统调用。xbionic中每个系统调用函数都由一小块汇编代码实现,称为“syscallstub”,由“gensyscalls.py”脚本自动生成,但需要从“syscalls.txt”中取得对应的参数。syscalls.txt文件中包含了一份要生成的系统调用块列表,和相应的系统调用数宁标识符(arm和x86不一样),以及它的签名。

xbionic要支持除arm和x86指令集以外的处理器架构,就是需要修改相应实现。

(3)时间管理。time_t在32位cpu内核上定义为32位,如果是一个64位的版本,则需要避免“y2038”bug,但是内核的维护者认为,并不需要这样的版本。相反,android提供了相应的头文件,定义了一个time64_t类型和相关的函数,如mktime64()、localtime64()等。如果strftime()使用time64_t,“%s”格式所支持的日期应该大于等于2038。android还提供了非标准的strftime_tz()函数,它实际上是strftime()的一个变形,可以接受一个通过“structstrftimelocale”结构体定义的时间区域描述符。

(4)时区管理。当前时区的名字取决于tz环境变量,如果tz环境变量未定义,那么将使用linux系统名为“persist.sys.timezone”的系统属性。时区数据库和索引文件位于是在posix兼容路径“/usr/share/zoneinfo”中,而不是android系统“/system/usr/share/zoneinfo”中。

(5)关闭(off_t)。off_t和time_t一样,也是32位的,由于bsd的继承关系,所以将loff_t型定义为64位变量,但是可以使用typedef定义off64_t类型,便于移植linux的glibc代码。

(6)linux内核头文件。android自带一套经过特殊处理的linux内核头文件,允许用户空间代码使用内核特有的声明(如ioctl、structuredeclaration、constant等)。这些头文件由一个脚本自动产生,只包含原始linux内核头文件中的公有定义。

(7)pthread实现。pthread是linux平台最核心的基础库之一,android的bionic的c库引入了自己的pthread实现,与linux平台的pthread实现并不兼容,xbionic中pthread的实现就需要依赖国产linux标准的pthread库实现android运行环境依赖的pthread库,同时确保与android的pthread的数据结构和语义的一致性,xbionic的pthread实现主要有以下特征:

√开放含有少量符号的链接器入口用于动态链接。

√xbionic不支持pthread_cancel(),因为它将使c库变得过于复杂。主要基于以下几点考虑:

■若要实现,必须在xbionic库的多个地方插入pthreadcancellation检测,这会使代码的统一调试变得非常困难。

■若要实现,就必须清理资源,如释放内存、解锁互斥体等,而且必须确保资源清理的一致性且不能在清理过程中导致死锁,如果cancel恰好发生在复杂的多层函数中,很容易导致死锁。

■pthreadcancellation不能停止所有的线程,例如:对于无穷循环,它就无能为力。

■pthreadcancellation本身也有缺陷,与处理器架构密切相关,可移植性差。

因为这些与xbionic的设计目标相矛盾,所以xbionic暂不支持pthread_cance()。

√pthread_once()函数。在使用pthread_once()函数时不能在其回调函数中调用fork(),否则,当再次调用pthread_once()时,会在子进程中导致死锁。而且,不能在回调函数中抛出一个c++异常。另外,当前pthread_once()实现还缺少必要的多核安全双重检查锁定(屏蔽读写操作)。

此外,xbionic的futex的实现特点是尽可能提供短小精悍的代码实现通用操作,与标准pthread相比,主要有以下几点显著的差异:

√pthread_mutex_t和pthread_cond_t的每个类型都只有4个字节。

√支持normal、recursive和error-check互斥体,对normal分支下的代码流程做了很细致的忧化,通常大多数时候都使用normal。

√不支持进程共享互斥和条件变量。因为它们的实现很复杂,且android用不到(android使用其他的进程内同步组件)。

√对读写锁、互斥体的优先权和其他高级特征的支持是可选的,默认是不支持的,因为android应用均不需要这些功能。

(8)线程相关数据处理(thread-specificdata)。线程本地存储区仅为每个进程提供了64个pthread_key_t对象,在实现上,提供了64个实时slot,而且自己使用了大约5个。需要注意的是,posix标准要求至少128个slot,因此xbionic与posix并不完全兼容。除了主线程,xbionic在栈顶部也设置了线程局部存储区。此外,为了与android的bionic一致,xbionic库和动态链接器均不支持使用_thread关键词来定义线程本地存储区。

(9)多核支持。xbionic提供的读/写内存屏蔽的需要处理器架构的支持,即处理器必须提供相应的操作原语。

(10)访问系统属性。android向系统中所有的进程提供了一个简单共享的键值对空间以及属性(property)的字符编码,每一个都是被限制大小的字符串,与一个被限制大小的字符串值相关联。相应的头文件既能够用于读系统属性,同时也定义键/值对的最大大小。xbionic用一块内存区域模拟了这个键值对空间。

(11)用户/组管理。在android中没有“/etc/passwd“或“/etc/groups”,因为手机在正常情况下都只有一个用户。另一方面,android使用扩展的linux用户/组管理特性,对不同的文件系统目录进行访问,以确保进程安全。xbionic将android运行环境的用户权限限制为linux当前用户的权限,以降低安全威胁。

(12)dns解析器。xbionic的dns解析器基于netbsd-derived解析库实现,与glibc相比具有以下特性:

√不实现“name-server-switch”特性;

√读取“/system/etc/resolv.conf”而不是“/etc/resolv.conf”;

√从系统属性中读取服务列表。代码查找“net.dnsl”、

“net.dns2”等。每个属性应包含一个dns服务器的ip地址。这些属性被android系统的其他部分修改(如:dhcpd进程)。同时,xbionic也支持“per-process”的dns服务器列表,使用属性“net.dnsl.<pid>”、“net.dns2spid>”等。这里<pid>代表当前进程的id号。

√在执行查询时,使用一个适当的随机查询id(而不是递堵1),以提高安全性。

√在执行查询时,给本地客户socket绑定一个随机端门号,以提高安全性。

(13)pthread实时定时器。xbionic支持timer_create()、timer_gettime()、timer_settime()和timer_getoverrun(),也支持sigev_thread实时定时器。

android的bionic简单地使用一个线程一个定时器的机制,而xbionic基于glibc实现了复杂的启发式技术。在多个定时器具有相同属性的情况下,可以显著减少使用的线程数。同时,如果代码使用许多sigev_thread定时器,程序也不会消耗太多内存。其他定时器(如sigfv_signal)则由内核处理,使用更少的系统资源。

(14)二进制兼容性。android的编译工具链不兼容glibc库、uclibc或其他的标准linux的c库,而xbionic和xdroid在国产linux平台的实现必须依赖glibc,直接在android应用中动态链接glibc将由于二进制不兼容导致崩溃。因此,xbionic需要修改编译android的工具链,使其编译的程序能够进行正确处理二进制不兼容的问题。

另外,对于不使用dlopen()/dlsym()的android应用,工具链可以直接依赖国产linux上的c库头文件通过静态链接的方式生成程序,相应的程序就可以在国产linux上正常运行。

(15)动态链接器。在linux中使用glibc的ld作为动态链接器(dynamiclinker),bionic使用自己的动态链接器linker,android应用依赖于xbionic的符号,而xbionic又会依赖glibc的符号,这两个动态库的导出的c函数大多重名。xbionic没有使用linker,而是通过修改glibc的ld链接器使其能够区分引用符号的一方是来自android应用还是来自xbionic,如是前者则使用xbionic的符号,如是后者则使用glibc导出的符号。

(16)c++异常支持。目前,android的标准bionic并不支持c++异常处理,xbionic将适当扩展,通过增加以下约束部分实现对c++异常的支持:

√如果在pthread_once的回调函数中抛出异常,xbionic将保持对应的pthread_once_t互斥器的锁定状态,再次调用pthread_once将导致死锁。

√如果从xbionic的回调函数中抛出异常,将可能会发生死锁。对android应用而言,这种情况非常少见。但是,在xbionic的实现机制下,应用为xbionic提供的回调不应抛出异常。

(17)包含路径。android编译工具链编译应用时需要必要的c库头文件的包含路径,xdroid的工具链能够自动分析xbionic的目录结构,相应地将库文件路径自动添加到c代码的包含路径中,包括libc/arch-$arch/include、libc/include或libc/kemel/arch-$arch等。

2、xbinder:基于请求代理模型的高效进程通信机制xbinder

基于通信方式、传输性能和安全性上要求,android设计并引入了一种新的进程通信模式binder。因此要实现android应用在国产操作系统上高性能兼容运行,桌面系统需要提供这样一种机制,同时不影响已有linux应用进程间的正常通信。如图3所示,本发明借鉴corba思想,在用户态实现基于请求代理模型的进程通信机制xbinder,xbinder内部基于linux的共享内存维护了一块数据交换空间,通过增加一次数据拷贝和相应的同步机制,实现了数据的一致性。xbinder基于client-server模式,传输过程只需一次拷贝,为发送方添加uid/pid身份,安全性高。

从内核态到用户态,提高安全性。基于安卓实现到国产操作系统实现。

xbinder机制的实现涉及到4类角色:xbinder服务(进程通信中介)、servicemanager(服务管理器)、server(服务方进程)和client(请求方进程)。

■client客户进程,代表了发起请求的进程。

■server服务进程,代表了响应请求的进程。

■servicemanager服务管理器。servicemanager是android系统各个服务的管理者,类似网络中dns的功能。android系统中的各个服务,都是添加到servicemanager中进行管理的,而且每个服务都对应一个服务名。当client获取某个服务时,则通过服务名来从servicemanager中查找获取相应的服务。

■xbinder服务。起到了类似于网络路由器的作用,任何请求与响应,都要经过xbinder这个中介进行处理。

3、xashmem:基于linux内存机制实现匿名共享内存机制xashmemxbinder每个进程接收数据的内存上限为1m,只要超过1m就会报错(xbinder无法分配接收空间),因此需要一种专门用来在ipc中传递大型数据的手段,除此以外需辅助内存管理系统对无效内存块进行管理,对于潜在的危险起到一定的防范作用,这正是android匿名共享内存机制(asynchronoussharedmemory,简称ashmem)设计的主要目的。

匿名共享内存机制xashmem以系统库的形式在用户态实现与ashmem接口一致,同时在系统运行时库层和应用程序框架层均提供了访问接口;其中,在系统运行时库层提供了c/c++调用接口,在应用程序框架层提供了java调用接口,java接口通过jni方法调用c/c++接口,逐步深入到内核,最终调用到xashmem;流程上,匿名共享内存机制xashmem提供并实现三个核心操作,分别是共享设备文件创建、共享文件到进程空间映射以及对共享内存空间进行读写操作。

二、图形加速渲染方面:基于国产处理器的国产操作系统平台与面向智能终端的android系统在图形加速方面有根本不同,如android平台的3d图形加速接口是opengles,而在桌面平台则是opengl。因此需要在兼容移动端图形加速接口的同时,充分发挥桌面系统的硬件资源优势,实现更高效的图形加速和3d渲染。

opengl是面向通用领域设计的,而为了适用手机等嵌入式领域,khronos对opengl进行了定制,形成opengles标准,各大手机图形处理器生产商基本都已提供支持,使得android系统有了更好的图形展示体验。但在国产桌面操作系统环境下,gpu环境发生了根本变化,gpu厂商只提供了opengl库,而不是面向手机图形处理器的opengles库,因此仅仅移植android自带的gpu图形加速功能是远远不够的,因为在国产桌面操作系统环境下无法使用。

本发明借鉴截获器思想,充分利用桌面平台gpu的硬件图形加速资源优势,xdroid对android的opengles系统进行重构,提出了基于opengl的图形加速器的模型xgr(xdroidforgraphicsrenderer),如图5所示。

图形加速器由验证层、翻译层以及渲染器三部分组成;也代表了实现xgr的三部分工作。

1、合法验证-验证层

这一部分工作类似于语言翻译前的单词拼写与语法检查工作。考虑到xgr是对android原有opengles基础库的重构,因此基于opengles的应用程序编译器前的预分析与检查验证工作在都由xgr在前完成。

2、功能翻译-翻译层

这一部分工作类似于编译器功能。尽管opengles是opengl的子集,但在数据类型等方面存在差异,如opengles没有double数据类型,而是加入了高性能的定点小数数据类型等等,xdroid针对这些描绘功能和管理功能的api以及所使用的参数数据类型进行了全面映射,转换成平台相关的功能和参数,即对android平台已有opengles的api翻译为系统相关的的图形api,并形成基础库。具体来说,主要需要完成以下两项工作:

一是全面梳理opengles与目标平台图形库(opengl)的差异;

二是基于差异和特定规则构建词法、语法等方面的映射基础规则库,以支持翻译的自动化。

3、渲染器实现-渲染器

核心就是重构openglesrenderer的实现模块。

一方面将与openglesrenderer相关的描绘模块简化抽象为接口(interface),即linux下的opengl将成为renderer的子类,以匹配系统平台。各个平台有各自的专有特性,为适配opengl,创建平台相关的上下文信息context,在此基础上,结合第二层的翻译情况,实现renderer代码来处理。

另一方面,与openglesrenderer相关的资源管理类也应简化抽象为接口形式,衍生出相应的实现类,如textureimpl,bufferimpl等,以适应不同平台的图形库,或同一个图形库的不同版本(opengl2.0、opengl2.5等)。

三、设备使用方面:

pc设备与手机设备大不相同,原先的移动端的设备接口及驱动库已不再适用。对于两个平台上具有类似功能的设备,本项目拟通过桥接技术使用pc平台的设备实现android设备的接口,如网络、音频、摄像头、鼠标、键盘、电源等;同时,通过设备接口虚拟技术模拟android应用会用到但pc一般不具备的设备,如gps等。

为了激励硬件设备生产商积极参与android生态建设,需要一种技术模式使得硬件设备驱动程序能够独立于linux内核,这样第三方厂商可以将自己不希望开源的二进制代码封装在这个特殊模块下,这种特殊模块统称为硬件抽象层(hardwareabstractionlayer,以下简称hal)。有了hal,android应用不依赖于某一个具体的硬件驱动,而是依赖于hal。在一定意义上讲,hal就是屏蔽硬件使用细节的“中间件”。只要hal向上层提供的接口不变,android应用就不需要做任何修改,可以很好地实现android应用对不同硬件的兼容性。

为了向应用提供访问相应硬件的功能,xdroid依照hal架构实现设备访问接口。

如图6所示,stub是对象代理,也就是硬件代理,在硬件抽象层注册每个硬件对象的代理,当上层需要访问硬件的时候,就从当前注册的硬件对象代理里查找,找到之后代理会向上层的运行时库提供该硬件对象的操作接口,该操作接口就保存在上层运行时库中,上层应用或框架再通过这个操作接口来访问硬件;

代理模式架构加载的共享库不包含操作底层硬件驱动的功能,仅保存代理提供的操作接口,底层代理扮演了“接口提供者”的角色,当代理第一次被使用时加载到内存,后续再使用时仅返回硬件对象操作接口,不会存在设备多次打开问题,并且由于多进程访问时返回的只是函数指针,代码不存在“代码重入”问题。因此代理模式能够更好地支持实现android应用跨平台运行。

如图7,以某一硬件设备led为例说明其工作机制。

led应用里的java代码不能操作硬件,将硬件操作工作交给本地运行时库led_runtime.so,它从当前系统中查找ledstub,查找到之后,ledstub将硬件驱动操作返回给led_runtime.so,ledapp操作硬件时,通过保存在led_runtime.so中的操作接口间接访问底层硬件。

综上,hal屏蔽了不同硬件设备的差异,为android提供了统一的访问硬件设备的接口。不同的硬件厂商遵循hal标准来实现自己的硬件控制逻辑,但开发者不必关心不同硬件设备的差异,只需要按照hal提供的标准接口访问硬件就可以了。

hal层帮助硬件厂商隐藏了设备相关模块的核心细节。有了hal层之后,硬件厂商可以把一些核心的算法之类的东西的实现放在hal层,而hal层位于用户空间,不属于linux内核,和android源码一样遵循的是apache协议,这个是可以开源或者不开的。

四、多媒体支持方面:

ndroid系统一般借助手机自带的dsp芯片,基于openmax实现音视频编解码功能,但在国产linux系统中,因芯片厂商出于专利保护等因素无法提供最佳适配,需要考虑采用跨平台的软解码方式或者开源的硬解码方式进行实现。

android多媒体组件涵盖播放流程的4大部分,包括读取datasource、分路demuxer、解码decoder和输出output,如图8所示;

数据源(source)处理主要是和协议打交道,音视频分解(demux)容器部分,大多数的容器格式的分解是不需要通过硬件来支持,因此基于前面运行时环境,android关于读取datasource和分离demuxer代码的移植工作在国产操作系统平台上仅需重新编译即可。而解码器与硬件关联性最为紧密,与硬件平台紧密相关,基于android的手机高清解码芯片都是“主芯片+dsp”结构,解码的工作都是通过dsp来做,不会再过多地占用主芯片的运算资源。所有dsp硬件编解码的能力通过openmax标准接口呈现出来,提供给上层播放器来用。但国产计算机和操作系统平台不同于手机终端,因此android自带的openmax编解码已不再适合,需要设计实现新的编解码服务组件(库)。为此,需要对openmax的实现架构和调用流程进行重新设计实现。

如图9所示,本发明抽象了一层omxcodec,提供给上层播放器用。播放器中音视频解码器videosource、audiosource都是omxcodec的实例。omxcodec通过iomx借助xbinder机制使用omx服务,omx把软编解码和硬件编解码统一看作插件的形式管理起来,因此omx服务插件就是openmax在android中的实现体。

omx借助omxmaster和omxnodeinstance实现了一个可扩展类似插件的编解码组件应用框架。omx通过这两个成员来创建和维护不同的openmax解码器组件,为多媒体播放器中不同解码提供服务。具体实现流程如下:

1、omx中omxnodeinstance负责创建并维护不同的实例,这些实例是根据应用需求创建的,以node作为唯一标识。这样播放器中每个omxcodec在omx服务端都对应有了自己的omxnodeinstance实例。

2、omxmaster维护底层软硬件解码库,根据omxnodeinstance中想要的解码器来创建解码实体组件。

以软解码和avc视频为例,解码器创建的流程如下:

omxmaster负责omx中编解码器插件管理,软件解码和硬件解码都是使用omx标准,挂载plugins的方式来进行管理。软解通过addplugin(newsoftomxplugin)挂载。

硬件编解码是通过addvendorplugin()加载libstagefrighthw共享库。各个dsp芯片厂商遵循openmax标准,生成libstagefrighthw共享库为android提供编解码支持。

voidomxmaster::addvendorplugin(){

addplugin("libstagefrighthw.so");

}

然后通过dlopen、dlsym来调用库中的函数,以上准备工作应在awesomeplayer的初始化过程中完成。

3、有了omx,接下来会创建videosource实例,执行参考代码如下:

omxmaster通过addplugin()把支持的软解码放在特定组件pluginbycomponentname中,omxmaster根据上面传入的解码组件的name值,在pluginbycomponentname找到相对应的解码组件plugin,然后调用plugin->makecomponentinstance()得到软解softomxplugin。例如是h.264格式,就加载libstagefright_soft_h264dec共享库,加载完h.264解码库后过dlopen、dlsym来调用库中函数。

通过调用softavc中的createsoftomxcomponent来创建真正h.264解码器实例softomxcomponent,以后真正视频解码的工作都是通过这个实例完成的。

有了上面的插件式实现框架,实现面向国产平台的编解码器,就是遵循omx接口标准规范,以插件的形式对omx接口进行实现,并按照android运行时环境要求的库形式进行编译并放置到android指定的位置。考虑到国产平台多样性,xdroid采用业界广泛使用ffmpeg开源编解码组件,按照openmax接口规范以及上述插件式框架要求进行改造,以共享库的形式为多媒体服务提供高效编解码功能。

实施例二

一种xdroid系统,包括计算机硬件系统、linux内核层、c/c++本地库与android运行时库、应用程序框架层和开发平台适配层,linux内核层、c/c++本地库与android运行时库经过实施例一所述方法处理;其中,应用程序框架层和开发平台适配层做下述修改:

应用程序框架层:为了保证android应用可直接流畅运行,就得确保面向应用的框架层在接口名称和语义上不能发生变化。因此,原先android系统的应用程序框架(applicationframework)的接口就不能修改,仅能修改其实现,且需要针对桌面系统及新增设备应用需求补充新的组件。

开发平台适配层:当前面向linux平台的android应用开发平台产品已经比较成熟,如androidstudio等,但xdroid与标准的android相比,在运行环境等方面发生了变化,需要针对xdroid的特殊之处,对开发环境与运行环境之间的交互接口与组件进行改造与适配。

以kylin-4.0.2-desktop-community(64位版)操作系统平台为例,说明基于xdroid系统的设备高性能模拟技术添加新设备的实现简要示例。

android设备接口的高性能模拟技术,本质上就是立足国产操作系统内核对hal进行重构,实质上规定了各类硬件设备驱动的编写标准,厂商遵循这些标准实现设备的控制逻辑,封装成上述的模块代理放到指定位置,确保能够让运行时库查询到即可。

(一)总体实施框架

hal这套标准也就是代理的实现结构,设计上主要是3个结构体、2个常量、1个函数,简称“321结构”。

1、三个结构体

每一个硬件都通过hw_module_t结构体来描述,称为一个硬件对象。新的硬件设备通过“继承”hw_module_t,扩展自己的属性来实现。硬件对象必须定义为一个固定的名字:hmi,即hardwaremoduleinformation,每一个硬件对象里都封装了一个函数指针open,用于打开该硬件返回这个操作该硬件设备对应的operationinterface。结构定义如下:

硬件对象hw_module_t的open方法描述结构体(即上述结构中的methods成员),只封装一个元素,即open函数指针。结构定义如下:

硬件对象hw_module_t的open方法返回该硬件的operationinterface,它由hw_device_t结构体来描述,封装了硬件的操作接口。

上述三个结构体之间关系紧密,每个硬件对象由一个hw_module_t来描述,只要获得这个硬件对象,就可以调用它的open方法,返回这个硬件对象的硬件操作接口,然后就可以通过这些硬件操作接口来间接操作硬件了。只不过,open方法被hw_module_methods_t结构封装了一次,硬件操作接口被hw_device_t封装了一次而已。这么做正是为了实现代理模式架构,同时实现硬件设备的可扩展性。

android应用要想获得所需要的硬件对象,一是需要定义硬件对象名字,二是根据名字能够找到所需要的对象,即定义一个方法。为此,xdroid设置两个常量和一个函数。

2、两个常量

硬件对象halstub对象固定的名字:

#definehal_module_info_symhmi

字符串形式的名字:

#definehal_module_info_sym_as_str"hmi"

3、一个方法

inthw_get_module(constchar*id,conststructhw_module_t**module);

通过硬件名来获得硬件hal代理对象,第一个参数id就是硬件名。当用户调用hw_get_module函数时,会从当前系统注册的硬件对象里查找传递过来的id名对应的硬件对象,然后返回之。

(二)具体实施步骤

根据上述hal框架和设计结构的基本思路,可以得知,实现设备正常高效运行的关键就是重构与设备相关的hal驱动。按照面向对象编程思想,hal标准(上述“321结构”)实质上就是为各种设备实体类提供了“抽象类”(c++语言称谓)或者“接口”,或者说一套模板,具体硬件设备(实体类)就可以通过“继承”和“派生”的方式进行实现并注册。但c语言不是面向对象编程语言,通过封装方式实现派生。

以上述led设备为例,大体思路实现如下:

1、继承派生hw_module_t结构体

结构体led_module_t封装了hw_module_t结构体,实现了“继承”在新结构体里可以再扩展一些新的成员,实现派生,创建名字为hal_module_info_sym的硬件对象。硬件对象名字固定,取用前面定义的常量。uml类图表示如图10所示。

2、继承派生hw_module_methods_t结构体

在上面的派生结构里,成员open函数指针(methods)自然也被子结构体给“继承”下来,初始化为led_module_methods的地址,该结构是hw_module_methods_t类型的,其声明代码如下:

led_device_open函数的功能:

√分配硬件设备操作结构体led_device_t,该结构体描述硬件操作行为

√初始化led_device_t的父结构体hw_device_t成员

√初始化led_device_t中扩展的操作接口

√打开设备,将led_device_t结构体以父结构体类型返回(面向对象里的多态)

hw_module_t与hw_module_methods_t及硬件open函数的关系如图11所示。

3、继承派生hw_device_t结构体

led_device_t和其父结构体hw_device_t的关系如下所示:

用uml类图来表示,如图12所示。

led_device_t扩展了三个接口:seton(),setoff()和get_led_count(),剩下的工作就是实现子结构中新扩展的三个接口。

这三个接口函数直接和底层驱动打交道去控制硬件,具体驱动部分在此不再展开。

以上在hal层扩展实现了led设备,为了确保android应用能够使用led设备,根据代理模式框架可以明确,还需在应用程序框架(java)和运行时库(jnic/c++)定义实现相关的接口,上下衔接,具体实现就不在赘述。

当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1