android开发与实践笔记(四)

来源:互联网 发布:openwrt 修改无线mac 编辑:程序博客网 时间:2024/04/30 08:57
第十四章 android启动过程详解
14.1 系统的启动过程
        在android中,在Bootloader记载系统映像后,会通过 system\core\rootdir\ 目录下的 init.rc 脚本进行初始化配置。
        在init.rc中可以配置系统时区,设置日志等级,设置全局环境变量,挂载文件系统,初始化网络配置,配置系统属性,启动守护进程等,具体过程如下:
              
          启动过程中的配置是系统正常运行的基本保证。
14.1.1 系统属性配置
      系统属性包括多个方面,在开机启动时,android将进行一系列的配置:
    》配置系统时区。android默认设置系统时区为GMT 0。设置系统时区的方法如下:   sysclktz 0  //东8区
    》设置日志等级。在android中,日志分为多个等级,设置控制台输出的日志等级,默认为3,设置方法:  loglevel 3
    》设置全局变量。系统启动过程中,android需设置全局变量,具体入下:
           
    》初始化网路配置。在android中,网络配置包括对lo和其他网络接入点的信息进行配置,配置网络参数的工具是 ifup, 具体如下:
                  ifup lo
                  hostname  localhost
                  demainname  localdomain
    》配置系统属性。可在编译脚本中对其进行设置。ActivityManagerSerivice中用到的一些配置 oom_adj 值的系统属性如下:     
                  
                  
         oom_adj值通常被android特有的内存管理驱动 Low memory killer使用,它会在系统内存低于设定值时释放响应的进程,保证系统的稳定运行。 Low memory killer 根据两个原则(进程的重要性和释放这个进程可获取的空闲内存数量)来决定释放的进程。 oom_adj 值越小,表示该类型的重要性越高。 oom_adj 相同的情况下,占用内存到的进程有限被撤销,进程占用的内存可用 get_mm_rss 进行判断。
14.1.2 文件系统挂载
        配置好文件系统分区并设置好分区表后,在设备实际启动前,需要挂载文件系统。
   1.  创建挂载点并设置权限
         完成环境变量设置后,接下来就是创建挂载点并根据安全需要设置相应的权限。对于敏感信息,应避免普通用于对其用于可写甚至可读的权限。权限的主要设置方法如下;
                
          以上可看出,android 有两个比较重要的用户权限,即 root,  system ,其中root 权限最高,对于系统和读写的路径至少应设置system权限。
    2. 挂载文件系统
          挂载点配置完成后,挂载文件系统。目前android默认的几个文件系统为system, data, cache等。挂载方法如下:
               
          默认情况下,android支持的问价系统类型为 yaffs2 。
 14.1.3 守护进程启动
        守护进程是运行在后台的android核心进程,主要包括 servicemanager, vold, netd, debuggerd,  ril-daemon, zygote, drm, drmio, media, bootanim, dbus, bluetoothd, hfag, hsag, opush, pbap, installd,  falsh_recovery, ravonn, mtpd, keystore, dumpstate 等。
    1. 守护进程的配置(在init.rc中完成)
         由于守护进程之间可能存在依赖关系,或守护进程对其他配置存在依赖,在启动进程时,需要做些配置。 在system\core\init\目录下的 readme.txt 中介绍了包括守护进程在内的启动项配置方法,其中守护进程的配置方法如下:
                 service  <name>  <pathname> [<argument>] *
                        <option>
                        ......
         上述代码中,option有多种情况:
                 
  2. 守护进程的启动
         下面介绍各守护进程的启动和配置和作用。
    (1)servicemanager
          系统服务的管理器,通过一个HashMap<String,  IBinder>来管理系统服务,当servicemanager重启时,会导致zygote和media重启。 下面是servicemanager的启动配置:
                 
     (2)vold的配置
           vold主要用来处理热插拔,其实际上就是负责完成系统的CDROM, USB大容量存储和MMC卡等扩展存储的挂载任务的守护进程。vold和linux标准的udev类似,均通过sysfs为内核和用于层提供通信。下面是vold的启动配置:
                          
           热插拔的处理框架:
                           
           和vold相关的代码主要位于 system/vold目录下。
   (3)netd
          主要用来监控网络状态,进行网络管理,其实现位于system\netd目录下,其启动配置如下:
                        
    (4)debuggerd
          主要用于调试,启动后会监听UNIX套接字 android:debuggerd, 其实现位于system\core\debuggerd目录下, 其启动配置如下:
                         
    (5)ril-daemon
           RIL守护进程会初始化芯片厂商的RIL, 管理所有来自Android通信服务的通信,通过套件字实现与芯片厂商的RIL的通信,其实现与hardware/ril/rild无关,配置过程如下:
             
Android的RIL位于应用程序框架与内核之间,分成了两个部分,一个部分是rild,它负责socket与应用程序框架进行通信。另外一个部分是Vendor RIL,这个部分负责向下是通过两种方式与radio进行通信,它们是直接与radio通信的AT指令通道和用于传输包数据的通道,数据通道用于手机的上网功能。
对于RIL的java框架部分,也被分成了两个部分,一个是RIL模块,这个模块主要用于与下层的rild进行通信,另外一个是Phone模块,这个模块直接暴露电话功能接口给应用开发用户,供他们调用以进行电话功能的实现。
                          
   (6)zygote
              是android启动后启动的第一个linux进程,其他的linux进程,比如各个应用,均是由zygote产生的。关于zygote的实现可参考ZygoteInit.java。zygote服务的重启会导致media和netd服务的重启,其启动配置如下:
                         
   (7)drm
         用于数字版权保护,其启动配置如下:
                         
   (8)drmio
          同样用于数字版权保护,配置如上
   (9)media
          提供多媒体服务的守护进程,它会启动 AudioFlinger,  MediaPlayerSerivce,  CameraService,  AudioPolicySerivce等服务。media服务的入口实现如下:
               
         media服务的启动配置如下:
                    
   (10)bootanim
          即所谓的开机动画服务,其具体实现位于BootAnimation.cpp中。 SurfaceFlinger 在完成准备工作后会在reayToRun()方法中,通过 porperty_set("ctl.start", "bootanim") 启动bootanim服务。在bootanim服务启动过程中,会加载用户开机动画和系统开机动画,均为zip格式,所在的位置为 data\local\bootanimation.zip,  和 \system\media\bootanimation.zip。动画中图片的格式应为RGB565,其实现位于frameworks\base\cmds\bootanimation目录中,bootanim服务的启动配置如下:
                     
     (11)dbus
            dbus和OpenBinder一样都是进程间的通信机制,android进程间通信主要利用的是OpenBinder, dbus仅用于蓝牙协议栈Bluez中。启动配置如下: 
                         
      (12)bluetoothd
              为bluez的守护进程,默认是不启动的。启动配置入下:
                               
       (13)hfag
                也用于Bluez, 作用是启动蓝牙免提音频网关,默认不启动。         
       (14) hsag
                  也用于Bluez, 作用是启动蓝牙耳机音频网关,默认不开启
       (15)opush 
                 实现 Exchange  ActiveSync服务器协议,同样也用于Bluez。默认不启动
        (16)installd
                 安装守护线程,用于apk的安装
        (17)flash_recovery
                  用于系统发生故障时的恢复。
        (18)racoon
                  是VPN的守护进程。
14.2  应用的启动过程
       AAPT允许开发者查看,创建,更新与ZIP箭筒的压缩文件(ZIP, JAR, APK),同时还将资源编译到断言(asset)中。
       APK包中,通常可以看到res,  AndroidManifest.xml, classes.dex,  resource.arsc, META-INF 和libs等几项。其中 META-INF 中存放的是Android的数字签名证书。
       需要说明的是,在android中,采用的java混淆器为开源的ProGuard4.4。ProGuard可以在一定程度上防止别人的窥视,但对于需要保护的敏感信息,其安全性是无法保证的。
       android生成的java字节码为DEX字节码,而非传统的CLASS字节码,但编译过程中,是先将java 文件编译为 CLASS字节码,然后将 CLASS字节码转化为 DEX字节码。
14.2.1 应用的启动配置
       android应用由一个继承了ContextWrapper的Application构成,其中Application由 Activity, Service, Receiver, Provider, uses-library等组件构成。组件之间的关系:
         
         需要注意的是,应用程序并非必须具有activity,如果仅是后台程序,仅有application也是可以的。
         如果不希望应用在系统低内存时被系统销毁,需将application标签的 android:persistent 属性设置为 true.
14.2.2 应用的启动过程
        要启动一个应用,首先要创建一个进程,然后启动UI主线程,接着打开Activity,具体流程如下:
                    
        android进程分为zygote进程和普通进程。当启动一个应用时,Dalvik虚拟机会先通过 NativeStart 接口初始化JNI,为通过 zygote进程创建新进程做好准备。原生代码的启动位于:  app_main.app中


  第十五章  深入解析android系统管理
15.1 内存管理
      在创建进程时,Dalvik虚拟机会为每个进程分配一定量的堆内存。占用内存较多的程序很容易引起OutOfMemoryError等异常。
      在数据交换比较频繁的场景中,多用SQLite来进行缓存。
 15.1.1 对应引用
          java对象的引用被分为 强引用(HardReference), 弱引用(WeakReference), 软引用(SoftReference)和 虚引用(PhantomReference)等4个级别。
         强引用表示 即使虚拟机内存“吃紧”抛出了 OutOfMemoryError 异常,该类型的对象也不会被回收; 
         软引用表示 在虚拟机内存“吃紧”抛出了 OutOfMemoryError 异常前,该类型对象会被回收;
         弱引用 更适合那些数量不多,但体积较庞大的对象,弱引用对象最容易被回收
         虚引用一般没有实际意义,仅观察GC的活动状态,对于 测试比较实用,必须和引用队列(ReferenceQueue)一起使用。
         弱引用,软引用,虚引用均可与引用队列联合使用,当引用的对象被回收时,Dalvik会把该引用对象加入到与之关联的引用队列。
         默认情况下,创建的java对象均为强引用。创建引用队列的方法如下:
                   ReferenceQueue<String> rq = new ReferenceQueue<String>()
         创建一个弱引用,并将对象和引用对象关联的方法如下:
                   WeakReference<String> wf = new WeakReference<String>( str, rq );
15.1.2 垃圾回收策略
         android中,每个应用占据一个虚拟机,所以android的垃圾回收是基于应用进行的。
         在应用层,通过调用 System.gc() 可以调用垃圾回收器回收垃圾
         事实上,在android的原生代码层,通过引入引用计数机制,Android 同样实现了自动垃圾回收机制,相关的实现位于 \frameworks\base\include\utils\RefBase.h 中。几乎所有的原生类均继承了 RefBase类,RefBase类会维护对象的强引用和弱引用计数,一旦强引用计数为0, 对象自动释放自己。原生代码的垃圾回收机制如下图所示:
                 
            其中维护强引用的指针为 sp, 维护弱引用的指针为 wp(weak pointer), sp 和 wp 均依赖于 RefBase类,因此继承与RefBase类的原生类才具有自动垃圾回收的能力。
   1.  sp 的实现



待完善

0 0
原创粉丝点击