Base)是一个在结构下对Linux发行版的联合项目,使Linux操作系统符合软件系统架构,或文件系统架构标准的规范及标准。基于,统一UNIX规范及其他开放标准,共在某些领域扩展它们。详细情况请参考相关链接。
由应用程序提供的脚本应该需要接受一个指示其动作(action)的参数,目前包括:
在下列情况下,lsb脚本要求确保对其接受的动作(action)有其明确且合理的行为
对于这些行为,为了满足其一致性,最好使用/lib/lsb/init-functions脚本(后面分析)
在主流的Linux发行版版本中,一个软件包卸载(remove)时,并不会讲一些脚本,配置文件同时删除,除非你强制指定为清除(purge).因此,在你的lsb脚本最前面应该包括一个判断真正的可执行文件是否存在,类似于下面这个样子:
如果调用status动作,lsb脚本应该根据其状态返回下面的值:
因为lsb脚本有可能是由系统管理员在非标准的环境下手工运行,比如没有PATH,USER,LOGNAME等环境变量.因此lsb脚本不能依赖环境变量,它需要自己设定自己需要的变量或者使用缺省值.
为了使得chkconfig能识别并能管理init脚本,需要在脚本第二行(第一行是#!/bin/bash)其增加下面这样几行:
聚合全网技术文章,根据你的阅读喜好进行个性推荐
版本的好处是,相同的“二进制”运行在安装了 Java 8 运行时的各个平台上。Rust 版本的优势是,二进制文件占用较少的 CPU 和内存,并且不需...
聚合全网技术文章,根据你的阅读喜好进行个性推荐
深圳市奥思网络科技有限公司版权所有
为啥新发明一个Binider通信机制
Binder通信机制原理图
android内核三大核心成员介绍
整个Android生态系统工作原理概述
了解一个事物,往往要从其出身开始,这样才能完整地明白它到底是什么东西。Android的历史渊源要追溯到90年代初,Andriod之父 Andy Rubin还在苹果子公司开发第一代手机OS “MagicCap”开始。
我用一段话简短概述iPhone和Android,苹果和谷歌之间的争端的历史缘由:
的基础,简称IOS。后来1996年底,苹果公司又收购NeXT公司,这样Jobs又回到了苹果公司。
1990年,苹果公司的手持设备部门独立,特地成立了”GeneralMagic” 的子公司,研究手机操作系统。”Android之父” ,89年刚进苹果公司的26岁的年轻人——Andy Rubin,认定手机OS发展前景良好,也加入了这个部门, 参与了”MagicCap” OS的开发,后于95年离开了苹果公司。2003年,Andy Rubin创建了Android公司,仅仅22个月之后,2005年被谷歌收购!然后,谷歌Android部门立马投入展开了短信、手机检索等业务,同时基于Linux的通用平台也进入了开发。经过2年的研究,2007年11月5日, 、android.media等等。后者是一种基于寄存器的java虚拟机,Dalvik虚拟机主要是完成对生命周期的管理、堆栈的管理、线程的管理、安全和异常的管理以及垃圾回收等重要功能。不过,最新的AndroidL 5.0 将彻底抛弃Dalvik虚拟机,改用ART模式。
在Dalvik虚拟机中,因此应用程序每次运行的时候,一部分代码都需要重新进行编译,这过程需要消耗一定的时间和降低应用的执行效率,最明显的便是拖延了应用的启动时间和降低运行速度。
通过在安装应用程序时,自动对程序进行代码预读取编译(可能比较耗时,占用更多ROM内存),让程序直接编译成机器语言,免去了Dalvik模式要时时转换代码,实现高效率、省电、占用更低的系统内存、手机运行流畅。
Android核心系统服务依赖于Linux2.6内核,如安全性、内存管理、进程管理、网络协议栈和驱动模型。Linux内核也是作为硬件与软件栈的抽象层。驱动:显示驱动、摄像头驱动、键盘驱动、WiFi驱动、Audio驱动、flash内存驱动、Binder(IPC)驱动、电源管理等。
在下面的图中,绿色的大部分组件是基于Apache许可证开源,其余基于GPL、LGPL和BSD。
在Linux中,是以进程为单位分配和管理资源的。出于保护机制,一个进程不能直接访问另一个进程的资源,也就是说,进程之间互相封闭
在Android终端上的应用软件的通信几乎看不到这些IPC通信方式,取而代之的是Binder方式。
Binder使用Client-Server通信方式:一个进程作为Server提供诸如视频/音频解码,视频捕获,地址本查询,网络连接等服务;多个进程作为Client向Server发起服务请求,获得所需要的服务。要想实现Client-Server通信据必须实现以下两点:
必须有确定的访问接入点或者说地址来接受Client的请求,并且Client可以通过某种途径获知Server的地址
Reply协议来传输数据。例如在网络通信中Server的访问接入点就是Server主机的IP地址+端口号,传输协议为TCP协议。对Binder而言,Binder可以看成Server提供的实现某个特定服务的访问接入点, Client通过这个‘地址’向Server发送请求来使用该服务;对Client而言,Binder可以看成是通向Server的管道入口,要想和某个 Server通信首先必须建立这个管道并获得管道入口
也可以在这些底层机制上架设一套协议来实现Client-Server通信,但这样增加了系统的复杂性,在手机这种条件复杂,资源稀缺的环境下可靠性也难以保证。
socket作为一款通用接口,其传输效率低,开销大,主要用在跨网络的进程间通信和本机上进程间的低速通信。
消息队列和管道采用存储-转发方式,即数据先从发送方缓存区拷贝到内核开辟的缓存区中,然后再从内核缓存区拷贝到接收方缓存区,至少有两次拷贝过程。
共享内存虽然无需拷贝,但控制复杂,难以使用
0 |
Android作为一个开放式,拥有众多开发者的的平台,应用程序的来源广泛,确保智能终端的安全是非常重要的。终端用户不希望从网上下载的程序在不知情的情况下偷窥隐私数据,连接无线网络,长期操作底层设备导致电池很快耗尽等等。传统IPC没有任何安全措施,完全依赖上层协议来确保。
首先传统IPC的接收方无法获得对方进程可靠的UID/PID(用户ID/进程ID),从而无法鉴别对方身份。Android为每个安装好的应用程序分配了自己的UID,故进程的UID是鉴别进程身份的重要标志。使用传统IPC只能由用户在数据包里填入UID/PID,但这样不可靠,容易被恶意程序利用。可靠的身份标记只有由IPC机制本身在内核中添加。
其次传统IPC访问接入点是开放的,无法建立私有通道。比如命名管道的名称,system V的键值,socket的ip地址或文件名都是开放的,只要知道这些接入点的程序都可以和对端建立连接,不管怎样都无法阻止恶意程序通过猜测接收方地址获得连接
Server,Client,SMgr运行于用户空间,驱动运行于内核空间。这四个角色的关系和互联网类似:Server是服务器,Client是客户终端,SMgr是域名服务器(DNS),驱动是路由器。
Android进程间通信的底层,都是靠binder驱动传输信息, 如图:
和DNS类似,SMgr的作用是将字符形式的Binder名字转化成Client中对该Binder的引用,使得Client能够通过Binder名字获得对Server中Binder实体的引用。注册了名字的Binder叫实名Binder,就象每个网站除了有IP地址外都有自己的网址
。 Server创建了Binder实体,为其取一个字符形式,可读易记的名字,将这个Binder连同名字以数据包的形式通过Binder驱动发送给 SMgr,通知SMgr注册一个名叫张三的Binder,它位于某个Server中。驱动为这个穿过进程边界的Binder创建位于内核中的实体节点以及 SMgr对实体的引用,将名字及新建的引用传递给SMgr。SMgr收数据包后,从中取出名字和引用填入一张查找表中。
Server向SMgr注册了Binder实体及其名字后,Client就可以通过名字获得该Binder的引用了。Client也利用保留的0号引用向SMgr请求访问某个Binder:我申请获得名字叫张三的Binder的引用。
SMgr收到这个连接请求,从请求数据包里获得Binder的名字,在查找表里找到该名字对应的条目,从条目中取出Binder的引用,将该引用作为回复发送给发起请求的Client。从面向对象的角度,这个Binder对象现在有了两个引用:一个位于SMgr中,一个位于发起请求的Client中。
如果接下来有更多的Client请求该Binder,系统中就会有更多的引用指向该Binder,就象java里一个对象存在多个引用一样。而且类似的这些指向Binder的引用是强类型,从而确保只要有引用 Binder实体就不会被释放掉。。
处理多线程的时候,Android继承了java的消息队列机制。
Android系统的消息队列和消息循环都是针对具体线程的,一个线程可以存在(当然也可以不存在)一个消息队列和一个消息循环(Looper),特定线程的消息只能分发给本线程,不能进行跨线程,跨进程通讯。但是创建的工作线程默认是没有消息循环和消息队列的,如果想让该线程具有消息队列和消息循环,需要在线程中首先调用Looper.prepare()来创建消息队列,然后调用Looper.loop()进入消息循环。
在android中,大部分的应用程序进程都是由zygote来创建的,为什么用大部分,因为还有一些进程比如系统引导进程、init进程等不是有zygote创建的。相反,zygote还是在init进程之后才被创建的。
注:init进程是盘古开天地级别的进程。
建立运行时环境并启动虚拟机,
为应用程序创建DVM进程。
Zygote进程运行示意图
PackagemanagerService主要管理apk,其实就是管理其中的组件等,如Activiey、Service,从apk中解析其中的组件,保存到相关结构中,以使得后面可以通过相关的接口可以查询系统安装组件,apk的安装,卸载,删除都是由PackageManagerService负责的。
简言之:PMS 掌管APK的生死,手里有本生死簿,类于阎王。
Android上发生的事件,例如,触屏,按钮什么的都是由WMS获取的。并且WMS负责了窗口的显示和控制。
另外包括了两个消息处理的类KeyQ和InputDispatcherThread,前者是WMS的内部类,当它有一个对象建立的时候,将会监听UI上所有的用户操作,包括触屏,按键等,并且把消息放到队列当中,等待应用的调用。后者的话主要负责从前者放入的消息队列(QueueEvent)当中获取相应的消息并且以一定规则予以消息的过滤,并且发放到相应的应用程序当中,类的作用可以顾名思义。
View是什么了,每个人都有自己的理解。在Android的官方文档中是这样描述的:这个类表示了用户界面的基本构建模块。一个View占用了屏幕上的一个矩形区域并且负责界面绘制和事件处理。View是用来构建用户界面组件(Button,Textfields等等)的基类。ViewGroup子类是各种布局的基类,它是个包含其他View(或其他ViewGroups)和定义这些View布局参数的容器。
包含有Activity的客户端程序至少包含3个线程,(每个Binder对应一个线程)
Android生态系统工作原理图:
apk程序的运行过程 (一) 前期准备
(看上面大图的中上角,或者看下面的局部截图)
然后创建一个ActivityThread对象,在ActivityThread的初始化代码中会创建一个H(Handler)对象和一个ApplicationThread(Binder)对象。其中Binder负责接收远程AmS的IPC调用,接收到调用后,则通过Handler把消息发送到消息队列中,UI主线程会异步的从消息队列中取出消息并执行相应的操作,比如start
接着UI主线程调用Looper.loop()方法进入消息循环体,进入后就会不断的从消息队列中读取并处理消息。
(看上面大图的中间部分,或者看下面的局部截图)
创建完成后,Activity需要把创建好的界面显示到屏幕上,于是调用WindowManager类,后者于是创建一个ViewRoot对象,该对象实际上创建了ViewRoot类和W类,创建ViewRoot对象以后,WindowManager再调用WmS提供的远程调用接口完成添加一个窗口并显示到屏幕上。
apk程序的运行过程(三) 响应用户屏幕操作
(看上面大图最左侧,或者看下面的局部截图)
接下来,用户开始在程序界面上操作,KeyQ线程不多把用户消息存储到QueueEvent队列中,InputDispatcherThread线程逐个取出消息,然后调用WmS中的相关函数处理该消息,当WmS发现该消息属于客户端某个窗口时,就会调用相应的窗口W接口。
本文仅从总体概念和基本原理上,介绍了Android系统的基本架构、核心功能组件和工作原理,由于篇幅所限,不可能就每章每点都详细讲解,只是蜻蜓点水,一掠而过,只希望能激发初学者的好奇心,通过本文所撕开的Android外衣的一角,让你窥到一点秘密,激起你对Android的兴趣。如果想继续深入了解Android的深层原理,还需要大家一起研究学习讨论。让我们一起,继续向Android的最高殿堂前进!
版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。