Android系统启动过程学习

转载 2018年04月16日 09:49:20

                            <div class="markdown_views">
                        <p>使用 android 手机已经长时间了,同时,从大学学习 android 开发开始,也进行过多款 android app 项目的开发,但是对 android 内部的启动过程,即当我们从按下电源键开机开始, android 系统内部是如何运行的,由于android  系统的内核使用的是 linux 内核,那么在启动过程中,android 系统和桌面Linux系统的启动过程是否是一样的?我们在之前的一篇博客中,曾学习过Linux内核的启动过程,在这里,我们学习一下android系统的启动过程,并从大体代码上讲解其启动过程。</p>



<h2 id="启动步骤"><a name="t0"></a>启动步骤</h2>

<p>在android系统的启动过程中,大体可以分为以下几个步骤:</p>

<p><img src="https://img-blog.csdn.net/20161221100119068?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaG9uZ2JvY2hlbjEyMjM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描述" title=""></p>



<h2 id="android启动过程分析"><a name="t1"></a>android启动过程分析</h2>



<h3 id="第一步-启动电源以及启动系统"><a name="t2"></a>第一步 启动电源以及启动系统</h3>

<p>当电源按下的时候,会引导固化在芯片中的代码从预定义的位置开始启动,并加载引导程序到内存,即RAM中,然后执行。</p>



<h3 id="第二步-引导程序运行"><a name="t3"></a>第二步 引导程序运行</h3>

<p>引导程序,英文名称为Boot Loader,顾名思义,其为启动加载器,其主要作用是引导android系统内核的启动。引导程序是运行的第一个程序。其主要作用是在引导内核启动之前,检测相关硬件以及外部的RAM,设置网络,内存等,并根据相关参数或输入数据设置内核。 <br>
Boot Loader引导程序可以在<code>\bootable\bootloader\legacy\usbloader</code>中找到,一般的加载器包含着两个重要的文件:</p>

<ol>
<li>init.S初始化堆栈,清空BBS栈,调用main.c的_main()函数</li>
<li>main.c初始化硬件(闹钟,主板,键盘,控制台),创建Linux标签</li>
</ol>

<h3 id="第三步-内核运行"><a name="t4"></a>第三步 内核运行</h3>

<p>当引导程序引导内核启动之后,android的内核运行和linux的内核运行相似。内核启动的时候,设置缓存,被保护的存储器,计划列表,加载驱动。当内核完成系统设置之后,便找到系统文件中”init”文件,然后启动系统的第一个进程。</p>



<h3 id="第四步-init运行"><a name="t5"></a>第四步 init运行</h3>

<p>init进程是android系统运行的第一个进程,也就是说所有的android进程都是直接或间接的被init进程创建的。在init进程运行过程中,主要负责两个事情,一个是挂载系统目录,像<code>/dev</code>,<code>/proc</code>,<code>/sys</code>等,另外一件事情是执行<code>init.rc</code>文件。</p>

<ul>
<li><code>init</code>位于<code>/system/core/init</code>目录中。</li>
<li><code>init.rc</code>位于<code>/system/core/rootdir</code>目录中。</li>
<li>在<code>/system/core/init/readme.txt</code>文件中可以学习<code>.rc</code>文件的相关语法,我们将在下面的博客中学习该语法。</li>
</ul>

<p>总体来说,在<code>init.rc</code>文件中,主要是启动相关进程和服务,同时设置相关参数和挂载相关目录。</p>

<p>我们先来看一下<code>init</code>中的相关代码:</p>



<pre class="prettyprint"><code class="language-stylus hljs perl has-numbering">
<span class="hljs-keyword">int</span> main(<span class="hljs-keyword">int</span> argc, char <span class="hljs-variable">**</span>argv)
{
    <span class="hljs-regexp">//</span>.....
<span class="hljs-comment">#ifndef NO_DEVFS_SETUP</span>
    <span class="hljs-keyword">mkdir</span>(<span class="hljs-string">"/dev"</span>, <span class="hljs-number">0755</span>);
    <span class="hljs-keyword">mkdir</span>(<span class="hljs-string">"/proc"</span>, <span class="hljs-number">0755</span>);
    <span class="hljs-keyword">mkdir</span>(<span class="hljs-string">"/sys"</span>, <span class="hljs-number">0755</span>);

    mount(<span class="hljs-string">"tmpfs"</span>, <span class="hljs-string">"/dev"</span>, <span class="hljs-string">"tmpfs"</span>, MS_NOSUID, <span class="hljs-string">"mode=0755"</span>);
    <span class="hljs-keyword">mkdir</span>(<span class="hljs-string">"/dev/pts"</span>, <span class="hljs-number">0755</span>);
    <span class="hljs-keyword">mkdir</span>(<span class="hljs-string">"/dev/socket"</span>, <span class="hljs-number">0755</span>);
    mount(<span class="hljs-string">"devpts"</span>, <span class="hljs-string">"/dev/pts"</span>, <span class="hljs-string">"devpts"</span>, <span class="hljs-number">0</span>, NULL);
    mount(<span class="hljs-string">"proc"</span>, <span class="hljs-string">"/proc"</span>, <span class="hljs-string">"proc"</span>, <span class="hljs-number">0</span>, NULL);
    mount(<span class="hljs-string">"sysfs"</span>, <span class="hljs-string">"/sys"</span>, <span class="hljs-string">"sysfs"</span>, <span class="hljs-number">0</span>, NULL);

    <span class="hljs-keyword">close</span>(<span class="hljs-keyword">open</span>(<span class="hljs-string">"/dev/.booting"</span>, O_WRONLY | O_CREAT, <span class="hljs-number">0000</span>));

    open_devnull_stdio();
    klog_init();
<span class="hljs-comment">#endif</span>
    property_init();

    <span class="hljs-regexp">//</span>.......

    is_charger = !strcmp(bootmode, <span class="hljs-string">"charger"</span>);

    INFO(<span class="hljs-string">"property init\n"</span>);
    <span class="hljs-keyword">if</span> (!is_charger)
        property_load_boot_defaults();

    INFO(<span class="hljs-string">"reading config file\n"</span>);

    <span class="hljs-keyword">if</span> (!charging_mode_booting())
       init_parse_config_file(<span class="hljs-string">"/init.rc"</span>);
    <span class="hljs-keyword">else</span>
       init_parse_config_file(<span class="hljs-string">"/lpm.rc"</span>);

    <span class="hljs-regexp">/* Check for an emmc initialisation file and read if present */</span>
    <span class="hljs-keyword">if</span> (emmc_boot &amp;&amp; access(<span class="hljs-string">"/init.emmc.rc"</span>, R_OK) == <span class="hljs-number">0</span>) {
        INFO(<span class="hljs-string">"Reading emmc config file"</span>);
            init_parse_config_file(<span class="hljs-string">"/init.emmc.rc"</span>);
    }

    /* Check <span class="hljs-keyword">for</span> a target specific initialisation file <span class="hljs-keyword">and</span> <span class="hljs-keyword">read</span> <span class="hljs-keyword">if</span> present <span class="hljs-variable">*/</span>
    <span class="hljs-keyword">if</span> (access(<span class="hljs-string">"/init.target.rc"</span>, R_OK) == <span class="hljs-number">0</span>) {
        INFO(<span class="hljs-string">"Reading target specific config file"</span>);
            init_parse_config_file(<span class="hljs-string">"/init.target.rc"</span>);
    }

    //.......
</code><ul style="" class="pre-numbering"><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li><li style="color: rgb(153, 153, 153);">21</li><li style="color: rgb(153, 153, 153);">22</li><li style="color: rgb(153, 153, 153);">23</li><li style="color: rgb(153, 153, 153);">24</li><li style="color: rgb(153, 153, 153);">25</li><li style="color: rgb(153, 153, 153);">26</li><li style="color: rgb(153, 153, 153);">27</li><li style="color: rgb(153, 153, 153);">28</li><li style="color: rgb(153, 153, 153);">29</li><li style="color: rgb(153, 153, 153);">30</li><li style="color: rgb(153, 153, 153);">31</li><li style="color: rgb(153, 153, 153);">32</li><li style="color: rgb(153, 153, 153);">33</li><li style="color: rgb(153, 153, 153);">34</li><li style="color: rgb(153, 153, 153);">35</li><li style="color: rgb(153, 153, 153);">36</li><li style="color: rgb(153, 153, 153);">37</li><li style="color: rgb(153, 153, 153);">38</li><li style="color: rgb(153, 153, 153);">39</li><li style="color: rgb(153, 153, 153);">40</li><li style="color: rgb(153, 153, 153);">41</li><li style="color: rgb(153, 153, 153);">42</li><li style="color: rgb(153, 153, 153);">43</li><li style="color: rgb(153, 153, 153);">44</li><li style="color: rgb(153, 153, 153);">45</li><li style="color: rgb(153, 153, 153);">46</li><li style="color: rgb(153, 153, 153);">47</li><li style="color: rgb(153, 153, 153);">48</li><li style="color: rgb(153, 153, 153);">49</li><li style="color: rgb(153, 153, 153);">50</li><li style="color: rgb(153, 153, 153);">51</li><li style="color: rgb(153, 153, 153);">52</li></ul></pre>

<p>在这些事情处理完成之后,在<code>init.rc</code>中便会启动zygote进程。</p>



<pre class="prettyprint"><code class="language-stylus hljs livecodeserver has-numbering">
service zygote /<span class="hljs-keyword">system</span>/bin/app_process -Xzygote /<span class="hljs-keyword">system</span>/bin <span class="hljs-comment">--zygote --start-system-server</span>
    class main
    <span class="hljs-built_in">socket</span> zygote stream <span class="hljs-number">660</span> root <span class="hljs-keyword">system</span>
    onrestart <span class="hljs-built_in">write</span> /sys/android_power/request_state wake
    onrestart <span class="hljs-built_in">write</span> /sys/power/state <span class="hljs-command"><span class="hljs-keyword">on</span></span>
    onrestart restart media
    onrestart restart netd
</code><ul style="" class="pre-numbering"><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li></ul></pre>



<h3 id="第五步-zygote进程"><a name="t6"></a>第五步 zygote进程</h3>

<p>在java中不同的虚拟机实例会为不同的应用分配不同的内存。假如android应用应该尽可能快的启动,但如果android系统为每一个应用启动不同的Dalvik虚拟机实例,就会消耗大量的内存以及时间。因此为了解决这个问题,Android系统创造了Zygote。Zygote让Dalvik虚拟机共享代码,低内存占用以及最小的启动时间成为可能。Zygote是一个虚拟机进程,正如我们在前一个步骤所说的在系统引导的时候启动。Zygote预加载以及初始化核心库类。</p>

<p>Zygote加载进程:</p>



<pre class="prettyprint"><code class="language-stylus hljs cs has-numbering">
 <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span>(String argv[]) {
        <span class="hljs-keyword">try</span> {
            <span class="hljs-comment">// Start profiling the zygote initialization.</span>
            SamplingProfilerIntegration.start();

            registerZygoteSocket();
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                SystemClock.uptimeMillis());

            preload();
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                SystemClock.uptimeMillis());

            <span class="hljs-comment">// Finish profiling the zygote initialization.</span>
            SamplingProfilerIntegration.writeZygoteSnapshot();

            <span class="hljs-comment">// Do an initial gc to clean up after startup</span>
            gcAndFinalize();

            <span class="hljs-comment">// Disable tracing so that forked processes do not inherit stale tracing tags from</span>
            <span class="hljs-comment">// Zygote.</span>
            Trace.setTracingEnabled(<span class="hljs-keyword">false</span>);

            <span class="hljs-comment">// If requested, start system server directly from Zygote</span>
            <span class="hljs-keyword">if</span> (argv.length != <span class="hljs-number">2</span>) {
                <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> RuntimeException(argv[<span class="hljs-number">0</span>] + USAGE_STRING);
            }

            <span class="hljs-keyword">if</span> (argv[<span class="hljs-number">1</span>].equals(<span class="hljs-string">"start-system-server"</span>)) {
                startSystemServer();  <span class="hljs-comment">//启动系统服务</span>
            } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (!argv[<span class="hljs-number">1</span>].equals(<span class="hljs-string">""</span>)) {
                <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> RuntimeException(argv[<span class="hljs-number">0</span>] + USAGE_STRING);
            }

            Log.i(TAG, <span class="hljs-string">"Accepting command socket connections"</span>);

            runSelectLoop();

            closeServerSocket();
        } <span class="hljs-keyword">catch</span> (MethodAndArgsCaller caller) {
            caller.run();
        } <span class="hljs-keyword">catch</span> (RuntimeException ex) {
            Log.e(TAG, <span class="hljs-string">"Zygote died with exception"</span>, ex);
            closeServerSocket();
            <span class="hljs-keyword">throw</span> ex;
        }
    }
</code><ul style="" class="pre-numbering"><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li><li style="color: rgb(153, 153, 153);">21</li><li style="color: rgb(153, 153, 153);">22</li><li style="color: rgb(153, 153, 153);">23</li><li style="color: rgb(153, 153, 153);">24</li><li style="color: rgb(153, 153, 153);">25</li><li style="color: rgb(153, 153, 153);">26</li><li style="color: rgb(153, 153, 153);">27</li><li style="color: rgb(153, 153, 153);">28</li><li style="color: rgb(153, 153, 153);">29</li><li style="color: rgb(153, 153, 153);">30</li><li style="color: rgb(153, 153, 153);">31</li><li style="color: rgb(153, 153, 153);">32</li><li style="color: rgb(153, 153, 153);">33</li><li style="color: rgb(153, 153, 153);">34</li><li style="color: rgb(153, 153, 153);">35</li><li style="color: rgb(153, 153, 153);">36</li><li style="color: rgb(153, 153, 153);">37</li><li style="color: rgb(153, 153, 153);">38</li><li style="color: rgb(153, 153, 153);">39</li><li style="color: rgb(153, 153, 153);">40</li><li style="color: rgb(153, 153, 153);">41</li><li style="color: rgb(153, 153, 153);">42</li><li style="color: rgb(153, 153, 153);">43</li><li style="color: rgb(153, 153, 153);">44</li><li style="color: rgb(153, 153, 153);">45</li><li style="color: rgb(153, 153, 153);">46</li><li style="color: rgb(153, 153, 153);">47</li><li style="color: rgb(153, 153, 153);">48</li><li style="color: rgb(153, 153, 153);">49</li></ul></pre>

<ol>
<li>加载<code>ZygoteInit</code>类,代码位于<code>/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java</code>中。</li>
<li><code>registerZygoteSocket()</code>为zygote命令连接注册一个服务器套接字。</li>
<li><code>preload()</code>预加载类,资源文件以及OpenGL。</li>
</ol>



<h3 id="第六步-系统服务或服务"><a name="t7"></a>第六步 系统服务或服务</h3>

<p>在Zygote完成相应的初始化之后,开始申请启动系统服务,系统服务是android系统中供上层运行的基础。系统服务同时使用native以及java编写,系统服务可以认为是一个进程。同一个系统服务在Android SDK可以让System Services形式获得。</p>

<p>核心服务:</p>

<ol>
<li>启动电源管理器;</li>
<li>创建Activity管理器;</li>
<li>启动电话注册;</li>
<li>启动包管理器;</li>
<li>设置Activity管理服务为系统进程;</li>
<li>启动上下文管理器;</li>
<li>启动系统Context Providers;</li>
<li>启动电池服务;</li>
<li>启动定时管理器;</li>
<li>启动传感服务;</li>
<li>启动窗口管理器;</li>
<li>启动蓝牙服务;</li>
<li>启动挂载服务。</li>
</ol>

<p>其他服务:</p>

<ol>
<li>启动状态栏服务;</li>
<li>启动硬件服务;</li>
<li>启动网络状态服务;</li>
<li>启动网络连接服务;</li>
<li>启动通知管理器;</li>
<li>启动设备存储监视服务;</li>
<li>启动定位管理器;</li>
<li>启动搜索服务;</li>
<li>启动剪切板服务;</li>
<li>启动登记服务;</li>
<li>启动壁纸服务;</li>
<li>启动音频服务;</li>
<li>启动耳机监听;</li>
<li>启动AdbSettingsObserver(处理adb命令)。</li>
</ol>



<h3 id="第七步-引导完成"><a name="t8"></a>第七步 引导完成</h3>

<p>一单系统服务启动,android系统的引导过程就完成了。此时,”ACTION_BOOT_COMPLETE”开机启动广播就发出去了。</p>                </div>
                                                <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/production/markdown_views-ea0013b516.css">
                                   

Android系统启动流程(四)Launcher启动过程与系统启动流程

此前的文章我们学习了init进程、Zygote进程和SyetemServer进程的启动过程,这一篇文章我们就来学习Android系统启动流程的最后一步:Launcher的启动流程,并结合本系列的前三篇...
  • itachi85
  • itachi85
  • 2017年02月23日 13:59
  • 8498

Android系统启动过程学习

使用 android 手机已经长时间了,同时,从大学学习 android 开发开始,也进行过多款 android app 项目的开发,但是对 android 内部的启动过程,即当我们从按下电源键开机开...
  • hongbochen1223
  • hongbochen1223
  • 2016年12月21日 10:03
  • 1033

Android系统启动过程分析

1. 系统启动流程简介 在linux里,每一个进程将有4G的空间,内核将这4G字节的空间分为两部分。最高的1G字节供内核使用,称为“内核空间”。而较低的3G字节供各个进程使用,称为“用户空间”。 ...
  • wh_19910525
  • wh_19910525
  • 2012年04月24日 20:47
  • 2855

Android系统启动过程,App启动过程

App启动过程:Activity启动过程详解从桌面点击到activity启动的过程1、Launcher线程捕获onclick的点击事件,调用Launcher.startActivitySafely,进...
  • semenry
  • semenry
  • 2016年08月31日 11:10
  • 273

Android系统启动过程

首先Android框架架构图:(来自网上,我觉得这张图看起来很清晰)    Linux内核启动之后就到Android Init进程,进而启动Android相关的服务和应用。 启动的过...
  • topstar_123
  • topstar_123
  • 2013年09月05日 17:26
  • 376

Android系统启动过程~~~

首先Android框架架构图:
  • yaodage110
  • yaodage110
  • 2014年05月13日 17:46
  • 348

android系统启动过程

Android的启动过程可以分为两个阶段,第一阶段是Linux的启动,第二阶段才是Android的启动,下面我们分别来了解一下具体的过程。 首先是Linux启动,这一部分我想就可以略过了,无非是...
  • chenli02
  • chenli02
  • 2014年05月14日 10:42
  • 287

Android启动过程图解

Bootloader、Kernel、Init、Zygote、SystemServer、ServiceManager、HomeLauncher
  • Amazing7
  • Amazing7
  • 2016年06月03日 14:10
  • 5806

Android系统启动流程(一)解析init进程启动过程

作为“Android框架层”这个大系列中的第一个系列,我们首先要了解的是Android系统启动流程,在这个流程中会涉及到很多重要的知识点,这个系列我们就来一一讲解它们,这一篇我们就来学习init进程。...
  • itachi85
  • itachi85
  • 2017年02月07日 11:29
  • 13017

Android系统启动过程浅谈

一、 系统启动流程简介 在Linux内核启动后,init 1(1号进程)将作为第一个用户空间(Linux虚拟内存的大小为232(在32位的x86机器上),内核将这4G字节的空间分为两部分。最高的1G...
  • kevin_hcy
  • kevin_hcy
  • 2014年02月18日 09:04
  • 3855
收藏助手
不良信息举报
您举报文章:Android系统启动过程学习
举报原因:
原因补充:

(最多只允许输入30个字)