[Android学习] 从按下电源键开始的系统启动分析

平时拿起手机开机的过程,我们都在无聊的等待中度过,而今天,我要钻一次牛角尖,我们来看看从按下电源键开始,手机系统做了哪些事情。

首先,Android系统是一个基于Linux的开源操作系统,x86(x86是一系列的基于intel 8086 CPU的计算机微处理器指令集架构)是linux内核部署最常见的系统。然而,所有的Android设备都是运行在ARM处理器(ARM 源自进阶精简指令集机器,源自ARM架构)上,除了英特尔的Xolo设备。Xolo来源自凌动1.6GHz x86处理器。Android设备或者嵌入设备或者基于linux的ARM设备的启动过程与桌面版本相比稍微有些差别。

下面是整个过程的示意图:
按下电源开关后Android设备执行了以下步骤

Android启动过程可以分为两个阶段,第一阶段是Linux的启动,第二阶段才是Android的启动。

Linux启动部分

引导程序

首先是Linux的启动,当按下电源的时候,引导代码会从预定义的地方(ROM)开始执行,加载到RAM执行。

引导程序是运行的第一个程序,所有这段代码是针对特定的主板和芯片的。OEM既可以选择受欢迎的引导程序比如redboot、uboot、qi bootloader 或者开发自己的引导程序,它不是Android操作系统的一部分,但是是厂商和运营商加锁和限制的地方。

引导程序分两个阶段执行。在第一个阶段,会检测外部的RAM和加载对第二阶段有用的程序;第二阶段是设置网络、内存等。这些对于运行内核是必须的,所以在一些特殊的情况下,引导程序可以根据配置参数或者输入数据设置内核。

引导程序可以在: \bootable\bootloader\legacy\usbloader 找到。这里面有些文件单独说明下:

1、init.s:初始化堆栈,清零BBS段,调用main_c的_main()函数;

2、main.c:初始化硬件(闹钟、控制台、主板、键盘),创建linux标签。

接着是Android的内核的启动,方式和Linux的启动方式差不多,都是设置缓存、被保护存储器、计划列表,加载驱动。当完成这些系统设置的时候,会在系统文件中寻找“init”文件,然后启动初始化root进程。

Android启动部分

init 进程

init是所有进程的父进程,它有两个任务,一个是挂载目录,比如:/sys、/dev、/proc,二个是运行init.rc脚本。

  • init进程可以在/system/core/init找到。

  • init.rc文件可以在/system/core/rootdir/init.rc
    找到。

  • readme.txt可以在/system/core/init/readme.txt找到。

下面是部分需要展示的init.c的main函数代码:

int main(int argc, char **argv)
{

    //step1 创建必要的文件夹 , 权限分配 7代表可读可写可执行  5代表可读可执行不可写  挂载磁盘
    mkdir("/dev", 0755);
    mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");

        //step2 初始化代码 包括日志初始化 配置文件初始化 以及硬件层初始化
    klog_init();
    property_init();


        //setp3 需要注意的一个初始化是init.rc配置文件的初始化   此处插入init.rc解读 详细请跳转  2.init.rc解读
    init_parse_config_file("/init.rc");

        //setp4 后续是很多的队列等待,等待初始化的完成,以及一些初始化失败的操作代码
    action_for_each_trigger("early-init", action_add_queue_tail);
    queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done");


    return 0;
}

init.rc文件

然后是 init.rc 文件的解读,.rc 文件是 Android 使用的初始化脚本文件 (System/Core/Init/readme.txt中有描述:four broad classes of statements which are Actions, Commands, Services, and Options.)。对于init.rc文件,Android中有特定的格式以及规则。在Android中,我们叫做Android初始化语言。Android初始化语言由四大类型的声明组成,即Actions(动作)、Commands(命令)、Services(服务)、以及Options(选项)。

Action(动作):动作是以命令流程命名的,有一个触发器决定动作是否发生。

比如:

250on late-init
251    trigger early-fs
252    trigger fs
253    trigger post-fs

Service(服务):服务是init进程启动的程序、当服务退出时init进程会视情况重启服务。

比如:

614service ueventd /sbin/ueventd
615    class core
616    critical
617    seclabel u:r:ueventd:s0

Commond(命令):就是系统支持的一系列命令,如:export,hostname,mkdir,mount,等等,其中一部分是 linux 命令,还有一些是 android 添加的,如:class_start < serviceclass >: 启动服务,class_stop < serviceclass >:关闭服务,等等。

Options(选项):选项是对服务的描述。它们影响init进程如何以及何时启动服务。

系统初始化要触发的动作和要启动的服务及其各自属性都在rc脚本文件中定义。init.rc 文件的一些事件和服务的举例:

Action/Service描述
on early-init设置init进程以及它创建的子进程的优先级,设置init进程的安全环境
on init设置全局环境,为cpu accounting创建cgroup(资源控制)挂载点
on post-fs改变系统目录的访问权限
service servicemanager启动系统管理器管理所有的本地服务,比如位置、音频、Shared preference等等…
service zygote启动zygote作为应用进程

这里我们就可以看到“Android”的 Logo 了。

Zygote

在Java中,我们知道不同的虚拟机实例会为不同的应用分配不同的内存。假如Android应用应该尽可能快地启动,但如果Android系统为每一个应用启动不同的Dalvik虚拟机实例,就会消耗大量的内存以及时间。因此,为了克服这个问题,Android系统创造了”Zygote”。Zygote 让 Dalvik 虚拟机共享代码、低内存占用以及最小的启动时间成为可能。Zygote是一个虚拟器进程,正如我们在前一个步骤所说的在系统引导的时候启动。Zygote预加载以及初始化核心库类。通常,这些核心类一般是只读的,也是 Android SDK 或者核心框架的一部分。在Java虚拟机中,每一个实例都有它自己的核心库类文件和堆对象的拷贝。

初始化建立的Service都是Native service,只有Zygote进程的建立才是真正的Android运行空间。

在 .rc 脚本文件中导入了服务器进程的包,看一下关联的文件:

 import /init.environ.rc
 import /init.usb.rc
 import /init.${ro.hardware}.rc
 import /init.${ro.zygote}.rc
 import /init.trace.rc

可以看到有一个import /init.${ro.zygote}.rc,找到 Zygote 的描述:

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
  class main
  socket zygote stream 666
  onrestart write /sys/android_power/request_state wake
  onrestart write /sys/power/state on
  onrestart restart media
  onrestart restart netd

参数:--zygote --start-system-server

上面的代码指向到:frameworks/base/cmds/app_process/app_main.cpp,打开发现:

int main( ){
       AppRuntime runtime;
       if (zygote) {
              runtime.start("com.android.internal.os.ZygoteInit",
                startSystemServer ? "start-system-server" : "");
       }
}

class AppRuntime : public AndroidRuntime{};

然后到了AndroidRuntime类中,该类的路径(frameworks\base\core\jni\AndroidRuntime.cpp):

void start(const char* className, const char* options){

       // start the virtual machine Java在虚拟机中运行的
       JNIEnv* env;
       if (startVm(&mJavaVM, &env) != 0) {
              return;
       }

       //向刚刚新建的虚拟机注册JNI本地接口
       if (startReg(env) < 0) {
              return;
       }

    // jni 调用 java 方法,获取对应类的静态main方法
    jmethodID startMeth = env->GetStaticMethodID(startClass,
         "main","([Ljava/lang/String;)V");

       // jni调用 java方法,调用到ZygoteInit类的main函数

       jclass startClass = env->FindClass(className);

       env->CallStaticVoidMethod(startClass, startMeth, strArray);
}

下面就到了ZygoteInit.java中的静态main函数中,从C++转向到JAVA,进入真的ZygoteInit进程(路径:/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java)。

public static void main(String argv[]) {
       //Registers a server socket for zygote command connections
       registerZygoteSocket();

       //Loads and initializes commonly used classes and
       //used resources that can be shared across processes
       preload();

       // Do an initial gc to clean up after startup
       gc();

       if (argv[1].equals("start-system-server")) {
              startSystemServer();
       }

       /**
       * Runs the zygote process's select loop. Accepts new connections as
       * they happen, and reads commands from connections one spawn-request's
       * worth at a time.
       */

       runSelectLoopMode();    //loop中
       /**
       * Close and clean up zygote sockets. Called on shutdown and on the
       * child's exit path.
       */
       closeServerSocket();
}

上述方法:

  1. registerZygoteSocket()为zygote命令连接注册一个服务器套接字;
  2. preloadClassed “preloaded-classes”是一个简单的包含一系列需要预加载类的文本文件,你可以在< Android Source >/frameworks/base找到“preloaded-classes”文件。
  3. preloadResources() preloadResources也意味着本地主题、布局以及android.R文件中包含的所有东西都会用这个方法加载,具体方法:
private static void preloadResources() {
    final VMRuntime runtime = VMRuntime.getRuntime();

    Debug.startAllocCounting();
    try {
        System.gc();
        runtime.runFinalizationSync();
        mResources = Resources.getSystem();
        mResources.startPreloading();
       //load资源数据
        mResources.finishPreloading();
    } catch (RuntimeException e) {
        Log.w(TAG, "Failure preloading resources", e);
    } finally {
        Debug.stopAllocCounting();
    }
}

Zygote就建立好了,利用Socket通讯,接收请求,Fork应用程序进程,进入Zygote进程服务框架中。

接着启动SystemServer,在Zygote进程进入循环之前,先调用startSystemServer( ):

private static boolean startSystemServer(){
       /* Request to fork the system server process 孵化新的进程 */
    ZygoteConnection.Arguments parsedArgs = null;
       pid = Zygote.forkSystemServer(
              parsedArgs.uid, parsedArgs.gid,
              parsedArgs.gids,
              parsedArgs.debugFlags,
              null,
              parsedArgs.permittedCapabilities,
              parsedArgs.effectiveCapabilities);

              /* For child process 对新的子进程设置 */
       if (pid == 0) {
              handleSystemServerProcess(parsedArgs);
       }
}

void handleSystemServerProcess(parsedArgs){
       closeServerSocket();
       //"system_server"
       Process.setArgV0(parsedArgs.niceName);

       //Pass the remaining arguments to SystemServer.
    RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
      parsedArgs.remainingArgs);
       /* should never reach here */
}

核心服务:

  1. 启动电源管理器;
  2. 创建Activity管理器;
  3. 启动电话注册;
  4. 启动包管理器;
  5. 设置Activity管理服务为系统进程;
  6. 启动上下文管理器;
  7. 启动系统Context Providers;
  8. 启动电池服务;
  9. 启动定时管理器;
  10. 启动传感服务;
  11. 启动窗口管理器;
  12. 启动蓝牙服务;
  13. 启动挂载服务。

其他服务:

  1. 启动状态栏服务;
  2. 启动硬件服务;
  3. 启动网络状态服务;
  4. 启动网络连接服务;
  5. 启动通知管理器;
  6. 启动设备存储监视服务;
  7. 启动定位管理器;
  8. 启动搜索服务;
  9. 启动剪切板服务;
  10. 动登记服务;
  11. 启动壁纸服务;
  12. 启动音频服务;
  13. 启动耳机监听;
  14. 启动AdbSettingsObserver(处理adb命令)

这里的服务启动都是在SystemServer.java类中执行:

1 . SystemServer的执行 init1()方法:

public static void main(String[] args) {

         System.loadLibrary("android_servers");    

         /*

         * This method is called from Zygote to initialize the system.
         * This will cause the native services (SurfaceFlinger, AudioFlinger, etc..)
         * to be started. After that it will call back
         * up into init2() to start the Android services.
         */
         init1(args);    //native 完了回调init2( )
  }

//init1:
  frameworks/base/services/jni/com_android_server_SystemServer.cpp:: android_server_SystemServer_init1( ) 
  中调用:system_init
extern "C" status_t system_init()
{
       sp<ProcessState> proc(ProcessState::self());
       sp<IServiceManager> sm = defaultServiceManager();

       //启动SurfaceFlinger 和传感器
       property_get("system_init.startsurfaceflinger", propBuf, "1");
       SurfaceFlinger::instantiate();

       property_get("system_init.startsensorservice", propBuf, "1");
       SensorService::instantiate();

       // And now start the Android runtime.  We have to do this bit
       // of nastiness because the Android runtime initialization requires
       // some of the core system services to already be started.
    // All other servers should just start the Android runtime at
       // the beginning of their processes's main(), before calling
       // the init function.
       AndroidRuntime* runtime = AndroidRuntime::getRuntime();


       //回调 com.android.server.SystemServer init2 方法      

       JNIEnv* env = runtime->getJNIEnv();

       jclass clazz = env->FindClass("com/android/server/SystemServer");

       jmethodID methodId = env->GetStaticMethodID(clazz, "init2", "()V");

       env->CallStaticVoidMethod(clazz, methodId);


       //启动线程池 做为binder 服务
       ProcessState::self()->startThreadPool();
       IPCThreadState::self()->joinThreadPool();
       return NO_ERROR;

}

ProcessState:

  每个进程在使用binder 机制通信时,均需要维护一个ProcessState 实例来描述当前进程在binder 通信时的binder 状态。

  ProcessState 有如下2 个主要功能:

  1. 创建一个thread, 该线程负责与内核中的binder 模块进行通信,称该线程为Pool thread ;

  2. 为指定的handle 创建一个BpBinder 对象,并管理该进程中所有的BpBinder 对象。

Pool thread:

  在Binder IPC 中,所有进程均会启动一个thread 来负责与BD 来直接通信,也就是不停的读写BD ,

  这个线程的实现主体是一个IPCThreadState 对象,下面会介绍这个类型。

  下面是Pool thread 的启动方式:

  ProcessState::self()->startThreadPool();

IPCThreadState :

  IPCThreadState 也是以单例模式设计的。由于每个进程只维护了一个ProcessState 实例,同时ProcessState 只启动一个Pool thread ,

也就是说每一个进程只会启动一个Pool thread ,因此每个进程则只需要一个IPCThreadState 即可。

Pool thread 的实际内容则为:

IPCThreadState::self()->joinThreadPool();

2 . SystemServer的执行 init2( ):

public static final void init2() {   
    //建立线程来处理
       Thread thr = new ServerThread();      
       thr.setName("android.server.ServerThread");
       thr.start();
}

//看看线程ServerThread里面都做了什么事情?
public void run() {
    addBootEvent(new String("Android:SysServerInit_START"));
    Looper.prepare();
    android.os.Process.setThreadPriority(
    android.os.Process.THREAD_PRIORITY_FOREGROUND);

    //初始化服务,创建各种服务实例,如:电源、网络、Wifi、蓝牙,USB等,
  //初始化完成以后加入到 ServiceManager中,
    //事我们用 Context.getSystemService (String name) 才获取到相应的服务
    PowerManagerService power = null;
    NetworkManagementService networkManagement = null;
    WifiP2pService wifiP2p = null;
    WindowManagerService wm = null;
    BluetoothService bluetooth = null;
    UsbService usb = null;
    NotificationManagerService notification = null;
    StatusBarManagerService statusBar = null;
    ……

    power = new PowerManagerService();
    ServiceManager.addService(Context.POWER_SERVICE, power);
    ……

    // ActivityManagerService作为ApplicationFramework最重要的服务
    ActivityManagerService.setSystemProcess();
    ActivityManagerService.installSystemProviders();
    ActivityManagerService.self().setWindowManager(wm);   
  // We now tell the activity manager it is okay to run third party
  // code.  It will call back into us once it has gotten to the state
  // where third party code can really run (but before it has actually
  // started launching the initial applications), for us to complete our
  // initialization.
  //系统服务初始化准备就绪,通知各个模块
    ActivityManagerService.self().systemReady(new Runnable() {

           public void run() {
                  startSystemUi(contextF);
                  batteryF.systemReady();
                  networkManagementF.systemReady();
                  usbF.systemReady();
                  ……

                  // It is now okay to let the various system services start their
                  // third party code...
                  appWidgetF.systemReady(safeMode);
                  wallpaperF.systemReady();
           }
    });

    //
    //BOOTPROF
    addBootEvent(new String("Android:SysServerInit_END"));
    Looper.loop();
}

到这里FrameWork层ServiceManager准备好了,进入到地一个上层应用HomeLauncher。在这个时候“ACTION_BOOT_COMPLETED”开机启动广播就会发出去。

Home界面启动

直接贴上代码:

 public void systemReady(final Runnable goingCallback) {
    ……
    //ready callback
       if (goingCallback != null)
              goingCallback.run();

       synchronized (this) {
              // Start up initial activity.
              // ActivityStack mMainStack;
              mMainStack.resumeTopActivityLocked(null);
       }
……

}

final boolean resumeTopActivityLocked(ActivityRecord prev) {
  // Find the first activity that is not finishing.
  ActivityRecord next = topRunningActivityLocked(null);
  if (next == null) {
    // There are no more activities!  Let's just start up the
    // Launcher...
    if (mMainStack) {
      //ActivityManagerService mService;
      return mService.startHomeActivityLocked();
    }
  }
  ……
}

至此,从按下电源键到手机启动,完成了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值