本文来自于CSDN博客,作者:天国1223,已获授权,版权归原作者全部,未经作者同意,请勿转载。
欢迎同有博客好文章的作者加微信(ID:tm_forever_miss)或直接邮件(mobilehub@csdn.net)投稿、约稿、给文章纠错。
在这篇文章中,我们将从代码角度细致学习Android体系的启动过程,同时,学习Android启动过程中的初始化脚本语言,即init.rc中的语言语法。在这里,不在具体先容Linux内核的启动过程,重要学习从Linux内核启动之后,init初始化是怎样工作的,他是怎样启动Android体系的第一个进程–Zygote进程。而且还会继承相识背面其他的进程是怎样通过Zygote进程启动的。话不多说,我们如今就来学习Android体系启动之路。
Android体系启动流程图
我们都知道,Android体系内核是基于Linux内核,以是在Android体系启动过程中,起首启动Linux内核,Bootloader加载并启动Linux内核,内核启动完成之后,内核开始启动Android体系的init进程,然后init进程通过init.rc启动脚本语言的实行,来启动Zygote进程,作为Android其他进程的父进程,Zygote进程做完初始化工作之后,启动SystemServer来启动其他体系服务。
下面我们从init进程的启动开始学习。
该文件位于system/core/init/init.cpp中,我们来看看init进程都做了哪些工作。
起首,init进程添加环境变量,而且挂载相应的目次。在主目次/之外为kmsg和null创建立备节点。初始化selinux,由于我们这里并不研究selinux的运行机制,以是其初始化细节也不在详究。根据起解释可以知道,假如当前体系处于内核域中,重新实行init来转换到init域中,由于SELinux战略已经被加载了。下面接着通过restorecon下令来将在selinux启动之前创建的目次的安全上下文规复到精确的属性。
接着,便是信号处理惩罚机制的初始化工作,加载启动属性,并启动属性服务器。下面,便进入至关紧张的一个函数,也是init进程的重要工作,便是实行init_parse_config_file("/init.rc")函数,该函数的重要作用就是分析init.rc文件,并实行init初始化进程语言。下面我们来看一下这个函数:
该代码位于system/core/init/init_parser.cpp中,该函数读取init.rc文件,并将数据传入到parse_config(path,data)函数中。
我们来看一下parse_config函数:
该函数和刚刚谁人函数位于同一个文件中,很显着,该函数用于分析读取的init.rc文件的字符串,该函数与文件parse.cpp中的next_token()函数共同,举行字符串的分析,然后通过调用parse_new_section()函数将services和actions等添加到运行队列中,等待trigger触发器的触发运行。
有关与Androidinitlanguage(Android初始化语言)我在博客AndroidInitLanguage(android初始化语言)中已经举行了具体的先容。下面我们接着看init进程中的main函数中所做的工作:
init.rc分析完成之后,全部的启动项目都被放入到action_add_queue_tail中,接着调用action_for_each_trigger("early-init",action_add_queue_tail),触发early-init触发器来出发这些相干services和actions的运行。
我们来看一下,在init.rc中,我们看early-init相干启动的services和actions。在这里根本上是规复某些文件或文件夹的安全上下文,然后调用init_zygote32_64.rc文件中的下令启动zygote。
这里的意思是通过/system/bin/app_process32程序启动zygote进程,参数为--zygote和--start-system-server,这两个参数在背面我们会用到的。下面我们来看一下Zygote的main函数。
该代码位于frameworks/base/core/Java/com/android/internal/os/ZygiteInit.java中。在代码中,他起首通过参数判定是否启动systemServer,也就是通过刚刚我们记录下来的参数--start-system-server判定startSystemServer为true;接着通过调用registerZygoteSocket(socketName)函数来注册zygote套接字,举行进程间的通讯,我们来看一下这个函数:
该代码位于同一个文件中,通过代码我们可以看到,创建zygote套接字的方式是通过创建一个LocalServerSocket对象来创建进程间的通讯,在解释中有阐明,注册一个服务套接字用于zygote下令毗连。
创建完成zygote套接字之后,实行preload()函数来举行资源文件的预加载工作。
在这里,加载类,加载资源文件,加载OPenGl,加载共享库,文本资源以及预备WebView。这里不在所说,我们接着往下看。
接着便调用startSystemServer(abiList,socketName)方法启动体系服务,我们来看一下这个函数:
在这里预备体系服启动的参数,并通过forkSystemServer来创建体系服务进程,接着调用handleSystemServerProcess(parsedArgs)来举行体系服务的处理惩罚。
在这里完成对创建的体系服务剩余的工作,末了调用RuntimeInit.zygoteInit将剩余的参数转达到体系服务中。
该函数位于同目次下面的RuntimeInit.java文件中。这里的nativeZygoteInit()用于进程间通讯的初始化操纵,applicationInit函数用于服务的启动,我们来看一下:
该函数重要是一些运行时的一些工作,同时调用invokeStaticMain来举行main函数的实行,看这个方法的解释,意思便是剩下的参数被转达,用于启动类的静态main函数。这里转达的类参数便是SystemServer类,以是这个函数的工作便是启动SystemServer的main函数。
该函数位于frameworks/base/services/java/com/android/server/SystemServer.java类中,这里运行SystemServer的run函数,该函数设置环境变量,启动其他服务,背面就不再赘述了。
接着返回到ZygoteInit.java的main函数中,这个函数末了实行runSelectLoop函数,这里运行一个循环,吸取新的毗连,读取来自毗连的下令。
至此,Android体系的启动过程就到了启动体系服务以及其他服务阶段了,背面我们会在别的博客中举行学习和讲授。
相识最新移动开辟、VR/AR干货技能分享,请关注mobilehub微信公众号(ID:mobilehub)。
我要评论