Android系统启动:

目录

 

Android系统启动流程图:

 

 

简述:

 

 

 

解析系统启动:

1.init进程启动过程:

 

 

1.1:init进程的入口函数:

 

1.2:属性服务:

 

 

1.3:解析init.rc:

 

 

1.4:init进程启动总结:

 

 

 

2.Zygote进程启动过程:

 

 

2.1:Zygote启动脚本:

2.2:Zygote启动流程:

 

 

2.3:Zygote启动流程总结:

 

 

 

3.SystemServer处理过程:

 

 

3.1:zygote处理SystemServer进程:

 

3.1.1:启动Binder线程池:

 

3.1.2:进入SystemServer的main方法:

 

 

3.2:解析SystemServer进程:

3.3:SystemServer进程总结:

 

 

 

4.Launcher启动过程:

 

 

4.1:Launcher启动过程介绍:

 

 

4.2:Launcher显示应用图标:


 

Android系统启动流程图:

 

6f3cc5a0f9184aff86fa4b03420d4f00.png

 

 

 

简述:

  1. 启动电源以及系统启动:当电源按下时引导芯片代码从预定义的地方(固化在ROM)开始执行。加载引导程序BootLoader到RAM,然后执行。
  2. 引导程序BootLoader:引导程序BootLoader是在Android操作系统开始运行前的一个小程序,它的主要作用是把系统OS拉起来并且运行。
  3. Linux内核启动:当内核启动时,设置缓存,被保护存储器,计划列表,加载驱动。当内核完成系统设置时,它首先在系统文件中寻找init.rc文件,并且启动init进程。
  4. init进程启动:它主要初始化和启动属性服务,并且启动Zygote进程。
  5. Zygote进程启动:创建Java虚拟机并且为Java虚拟机注册JNI方法,创建服务器端Socket,启动SystemServer进程。
  6. SystemServer进程启动:启动Binder线程池和SystemServer,并且启动各种系统服务。
  7. Launcher启动:被SystemServer进程启动的AMS会启动Launcher。它会将已经安装应用的快捷图标显示到界面上。

 

 

 

解析系统启动:

1.init进程启动过程:

init进程是Android系统中用户空间的第一个进程,进程号为1,是Android系统启动流程的一个关键步骤。init进程由多个源文件共同组成的,这些文件位于源码目录system/core/init中。

 

 

1.1:init进程的入口函数:

在Linux内核加载完成后,它首先会在系统文件中寻找init.rc文件,并且启动init进程。查看init进程的入口函数main(system/core/init/init.cpp),它在开始的时候创建和挂载启动所需的文件目录,其中挂载了tmpfs,devpts,proc,sysfs和selinuxfs共5种文件系统,这些都是系统运行时目录。然后调用property_init函数来对属性进行初始化,并且后续通过调用start_property_service函数启动属性服务。具体参考:1.2属性服务这一节。接着还有signal_handler_init函数用于设置子进程信号处理函数。它被定义在system/core/init/signal_handler.cpp中,主要用于防止init进程的子进程变成僵尸进程的。然后还有用于解析init.rc文件的函数(init.rc文件位于system/core/init/init_parse.cpp)。

 

僵尸进程:在unix/Linux中,父进程使用fork创建子进程,在子进程终止之后,如果父进程不知道子进程已经终止了,系统进程表还保存一定的信息,那么这个进程就叫做僵尸进程。因为系统进程表是一项有限的资源,如果被僵尸进程耗尽的话,系统就可能无法创建新的进程了。

为了防止僵尸进程的出现,系统会在子进程暂停和终止的时候发出SIGCHLD信号,而signal_handler_init函数就是用来接收SIGCHLD信号的,它的内部在接收之后会调用handle_signal函数,经过层层函数的调用和处理,最后会找到该子进程并且移除它的信息,再重启子进程服务的启动脚本中带有onrestart选项的服务。

 

 

1.2:属性服务:

在Windows平台上有一个注册表管理器,注册表采用键值对的形式来记录用户,软件的一些使用信息。即使在系统或者软件重启后,其还是能够根据之前注册表中的记录,进行相应的初始化工作。Android也提供了一个类似的机制,叫做属性服务。

property_init函数的实现过程:内部调用_systrm_property_area_init函数用来初始化属性内存区域。而start_property_service函数首先创建非阻塞的Socket(命名为property_set_fd),再调用listen函数对property_set_fd进行监听,使Socket成为server,也就是属性服务。接着把property_set_fd放入epoll中,让epoll来监听property_set_fd:当property_set_fd中有数据来到时,init进程会调用handle_property_set_fd函数进行处理。该函数也分两个分支,一个处理控制属性,一个处理普通属性。

 

 

1.3:解析init.rc:

init.rc是一个非常重要的配置文件,它是由Android初始化语言编写的脚本,这种语言主要包含5种类型语句:Action,Command,Service,Option和Import。

  1. 所有这些都是以行为单位,各种记号由空格来隔开。注释行以井号(#)开头。
  2. Actions和Services声明一个新的分组。所有的命令或选项都属于最近申明的分组。 Actions和Services都有唯一的名字。
  3. Action(动作):Actions其实就是一序列的Commands(命令)。 Actions有一个trigger触发器,该触发器用于确定操作的执行时间。 当事件发生与Action的trigger触发器匹配,该Action将添加到要执行的队列的尾部(除非它已经在队列)。 队列中的每个 action 按顺序排列,action 中的每个命令都按顺序执行。
  4. Service(服务):Init启动的程序,可以选择要不要在退出后重启。
  5. Command(命名):command是Actions的一部分,用于执行一条命名。
  6. Options(选项):是services的修饰符。它们影响init如何以及何时运行service。
  7. Import(导入):import关键字不是一个命令,而是一个部分,并在包含它的.rc文件完成解析后立即处理。

 

在init.rc中的Action类型语句和Service类型语句都有相应的类进行解析,前者使用ActionParser解析,后者使用ServiceParser解析。解析函数实现代码在system/core/init内。关于如何创建Zygote,主要查看Service类型语句,Zygote的启动脚本在system/core/rootdir目录下依据不同服务来定义。

ServiceParser解析主要使用两个函数:一个是ParseSection,用于解析Service的rc文件;一个是ParseLineSection,用于解析子项。解析过程主要是根据参数的不同创建出一个Service对象,然后根据选项域的内容填充Service对象,最后将该对象加入到vector类型的Service链表中。然后再到启动Zygote这个Service,过程如下(system/core/rootdir/init.rc):在该文件下有一句class_start main它就是用来启动Zygote的。其中class_start对应的函数为do_class_start,它的ForEachServiceInClass函数会遍历Service链表,找到classname为main的Zygote,并且执行StartIfDisabled函数,它会判断如果Service没有在对应的rc文件中设置disabled选项,则调用start函数来启动该Service,start函数会首先判断Service是否已经运行,如果运行就不启动,接着判断需要启动的Service对应的文件是否存在,不存在就不启动。然后还没有启动的话,调用fork函数创建子进程,并且返回pid值,在pid为0时调用execute函数启动Service子进程,并且进入该Service的main函数中,如果该Service是Zygote,就会进入到frameworks/base/cmds/app_process/app_main.cpp中,调用runtime的start函数启动Service(Zygote)。

 

 

1.4:init进程启动总结:

init进程主要做了:

  1. 创建和挂载启动需要的文件目录。
  2. 初始化和启动属性服务。
  3. 解析init.rc配置文件并且启动Zygote进程。

 

 

 

2.Zygote进程启动过程:

在Android系统中,DVM和ART,应用程序进程以及运行系统的关键服务的SystemServer进程都是由Zygote进程来创建的,我们也把它叫做孵化器。它通过fock(复制进程)的形式来创建应用程序进程和SystemServer进程,由于Zygote进程在启动时会创建DVM或者ART,因此通过fock而创建的应用程序进程和SystemServer进程可以在内部获取一个DVM或者ART的实例副本。

 

 

2.1:Zygote启动脚本:

在init.rc文件中采用了Import类型语句根据不同的ro.zygote属性值来引入不同的Zygote启动脚本,ro.zygote属性的取值有:init.zygote32.rc,  init.zygote32_64.rc,  init.zygote64.rc,  init.zygote64_32.rc。这些启动脚本都在system/core/rootdir目录下。而 init.zygote32_64.rc代表32位为主,64位为辅。

 

 

2.2:Zygote启动流程:

解析一下frameworks/base/cmds/app_process/app_main.cpp文件,在调用runtime的start函数启动Service(Zygote)之前,因为Zygote进程都是通过fock自身来创建子进程的,这样Zygote进程以及它的子进程都可以进入app_main_.cpp的main函数中,所以main函数中为了区分当前运行在哪个进程,会利用strcmp的参数判断。如果是运行在Zygote进程中,就会调用runtime的start函数启动Zygote。

这个start函数主要用于:首先调用startVM函数来创建Java虚拟机,并且调用startReg函数为Java虚拟机注册JNI方法。然后通过传入的参数classname,经过一系列的操作变成slashClassName,根据它找到ZygoteInit。接着JNI通过调用ZygoteInit的main方法(main方法在frameworks/base/core/Java/com/android/internal/os/zygoteinit.Java中)。从而让Zygote进入Java框架层。进入Java框架层后,main方法主要做了4件事:通过registerServerSocket方法创建一个server端的socket; 通过preload方法预加载类和资源;  通过startSystemServer方法启动SystemServer进程; 通过runSelectLoop方法来等待AMS请求创建新的应用程序进程。

 

解析main方法的3件事:

  1. registerServerSocket方法首先拼接socket名称,将该名称转换为socket环境变量的值,再转换为文件描述符的参数,接着创建文件描述符传入服务端的socket。这个socket在zygote进程将SystemServer进程启动后等待AMS请求zygote进程来创建新的应用程序进程。
  2. startSystemServer方法首先创建数组保存SystemServer的启动参数,然后将数组封装成Arguments对象给forkSystemServer函数调用。forkSystemServer函数内部会调用nativeForkSystemServer函数来通过fork函数在当前进程创建一个子进程,也就是SystemServer进程,如果pid为0,代表当前代码在子进程中运行,就执行zygoteserver.closeserversocket函数(因为systemserver进程复制了zygote进程的地址空间,因此得到了zygote进程的socket,所以这个socket对于systemserver没有作用,因此关闭);再使用handleSystemServerProcess方法来处理SystemServer进程。
  3. 启动SystemServer进程后,会执行runSelectLoop方法它通过mServerSocket.getFileDescriptor方法获取上面socket的文件描述符并且添加到列表fds中,接着无限循环AMS请求zygote进程创建新的应用程序进程,然后再把列表的信息存储在数组pollFds中,再判断i值,如果为0,说明socket和客户端连接上了,也就是当前zygote与AMS建立了连接,后续通过acceptCommandpeer方法得到ZygoteConnection类并且添加到socket的连接列表peers中,再将该类的文件描述符添加到fds中;如果i不为0,说明AMS已经发送了创建应用进程的请求,就后续调用ZygoteConnection的runOnce函数来创建一个新的应用程序进程,创建成功后把这个连接从peers和fds中去除。

 

 

2.3:Zygote启动流程总结:

  1. 调用runtime的start函数启动Zygote。
  2. 创建Java虚拟机并且为Java虚拟机注册JNI方法。
  3. 通过JNI调用ZygoteInit的main方法进入zygote的Java框架层。
  4. 通过registerServerSocket方法创建一个server端的socket;并且通过runSelectLoop方法来等待AMS请求创建新的应用程序进程。
  5. 启动SystemServer进程。

 

 

 

3.SystemServer处理过程:

systemserver进程主要用于创建系统服务。

 

 

3.1:zygote处理SystemServer进程:

在上面写到在zygoteinit.Java的startSystemServer方法启动SystemServer进程,并且在后续使用handleSystemServerProcess方法来处理SystemServer进程。那么在handleSystemServerProcess方法它主要做了:首先创建了PathClassLoader,然后调用了ZygoteInit的zygoteInit方法,它主要调用nativeZygoteInit方法启动Binder线程池,使SystemServer进程就可以使用Binder与其他进程通信。还有用于进入SystemServer的main方法。

3.1.1:启动Binder线程池:

上面写到nativeZygoteInit方法启动Binder线程池,这个方法也是一个Native方法。它对应的JNI文件在frameworks/base/core/jni/AndroidRuntime.cpp定义,而nativeZygoteInit方法对应该文件的com_android_internal_os_ZygoteInit_nativeZygoteInit函数。该函数使用了一个AndroidRuntime的指针gCurRuntime,指向AndroidRuntime的子类AppRuntime,它在framework/base/cmds/app_process/app_main.cpp定义,在该文件中,就使用了onZygoteInit方法启动一个Binder线程池。

3.1.2:进入SystemServer的main方法:

进入SystemServer的main方法是依靠RuntimeInit的appLicationInit方法(路径:frameworks/base/core/Java/com/android/internal/os/RuntimeInit.java),该方法内部主要调用了invokeStaticMain方法。invokeStaticMain方法主要先通过反射Class.forName获取systemserver类,再通过该类找到它的main方法,接着传入MethodAndArgsCaller异常中抛出异常,并且会在ZygoteInit.java的main方法中被捕获。捕获之后会调用MethodAndArgsCaller的run方法,该方法通过执行mMethod的invoke方法,使得SystemServer的main方法被动态调用,也就是SystemServer进程进入了SystemServer的main方法中。

使用这种方式是为了让抛出异常的处理会清除所有的设置过程需要的堆栈帧,并且让SystemServer的main方法看起来像是SystemServer进程的入口方法。

 

 

3.2:解析SystemServer进程:

在SystemServer的main方法(frameworks/base/services/java/com/android/server/SystemServer.java)中只调用了SystemServer的run方法,该方法主要首先加载了动态库libandroid_servers.so,再创建了SystemServerManager,它负责对系统服务进行创建,启动和生命周期的管理。后续的startBootstrapServices方法用SystemServerManager启动了引导服务;startCoreServices方法启动了核心服务;startOtherServices方法启动了其他服务。这三种服务父类均为SystemServer,且合称系统服务,而其他服务是一些非紧要和不需要立刻启动的服务。这些系统服务有100多种。

 

 

3.3:SystemServer进程总结:

SystemServer进程被创建后,主要做了:

  1. 启动Binder线程池。
  2. 创建SystemServerManager。
  3. 启动各种系统服务。

 

 

 

4.Launcher启动过程:

系统启动的最后一步就是启动一个应用程序用来显示系统中已经安装的应用程序,这个应用程序叫做Launcher。它会在启动过程中请求PackageManagerService返回系统中已经安装的应用程序的信息,并且将这些信息封装成为一个快捷图标列表显示在屏幕上,这样用户就可以通过点击这些快捷图标启动相应的应用程序。通俗来说Launcher就是Android系统的桌面,主要作用有:1.作为Android系统的启动器,用于启动应用程序。2.作为Android系统的桌面,用于显示和管理应用程序的快捷图标或者其他桌面组件。

 

 

4.1:Launcher启动过程介绍:

前面说到SystemServer进程的main方法会启动引导服务,而引导服务就包括启动PackageManagerService,它启动后会把系统中的应用程序安装完成。而在之前启动的AMS也会把Launcher给启动起来。启动Launcher的入口为AMS的systemReady方法,它在SystemService的startOtherService方法中被调用。而systemReady方法主要调用了ActivityStackSupervisor的resumeFocusedStackTopActivityLocked方法。resumeFocusedStackTopActivityLocked方法主要调用了ActivityStack的resumeTopActivityUncheckedLocked方法,其中ActivityStack对象的描述activity堆栈的,而它的方法主要调用了resumeTopActivityInnerLocked方法。而resumeTopActivityInnerLocked方法关键在于调用ActivityStackSupervisor的resumeHomeStackTask方法。在该方法的内部调用了AMS的startHomeActivityLocked方法。它首先判断系统的运行模式和第一个被启动的Activity组件的action值(其中运行模式有非工厂模式,低级工厂模式,高级工厂模式)。接着调用getHomeIntent方法创建Intent,然后把判断符合条件的应用程序还没有启动的,调用ActivityStarter的startHomeActivityLocked来启动应用程序,也就是启动Launcher。(systemReady方法在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java中定义)

 

 

4.2:Launcher显示应用图标:

Launcher完成启动后会做很多工作,作为桌面它会显示应用程序图标。流程为:首先是Launcher的onCreate方法,它主要先获取了LauncherAppState的实例,再把Launcher对象传入该实例的setLauncher方法中,接着调用了LauncherModel的startLoader方法。

setLauncher方法主要调用了LauncherModel的initialize方法,它会将Callbacks,也就是传入的Launcher封装为一个弱引用对象,所以Callbacks其实就是封装的Launcher对象。

LauncherModel的startLoader方法主要创建了具有消息循环的线程HandlerThread对象,后续传入它的Looper创建了Handler。这里的Handler作用是向HandlerThread发送信息。然后创建LoaderTask,将它作为消息发送给HandlerThread。LoaderTask又是LauncherModel的内部类,负责调用loadWorkspace方法和bindWorkspace方法加载和绑定工作区信息,再通过loadAllApps方法加载系统已经安装的应用程序信息。

Launcher是通过工作区的形式来显示系统安装的应用程序的快捷图标的,每一个工作区都是用来描述一个抽象桌面,它由N个屏幕组成,每个屏幕又是N个单元格,每个单元格显示一个应用程序的快捷图标。

loadAllApps方法主要调用了call backs的bindAllApplications方法,该方法会调用AllAppsContainerView类型的mAppsView对象的setApps方法,并且将包含应用信息的列表传入setApps方法内部设置AlphabeticalAppsList对象的setApps方法。而AllAppsContainerView的onFinishInflate方法在AllAppsContainerView加载完XML布局时调用,使用AllAppRecyclerView显示App列表,以及设置它为Adapter,这样应用程序快捷图标就显示在屏幕上了。

路径参考:packages/apps/Launcher3/src/com/android/launcher3/

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mo@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值