随着智能终端功能的越来越庞大,与之,硬件配置越来越高,开机时间却越来越长。人们在享受强大功能的同时,对冗长的智能终端的开机时间却越来越缺乏耐心。

为了“取悦”用户,需要提供较好的用户体验,那么就必须使得智能终端尽可能短的进入“可工作”状态。

       本文中的“尽可能短的开机时间”,“开机优化”、“开机时间优化”均表示同一个意思。

       如果计划对linux系统进行开机时间优化,那么就必须熟悉linux启动流程,本小节主要从框架上对Linux启动做简单的介绍,并不会详细的描述。

       如下图:

需要明确的是preloader、lk(Little Kernel)、kernel、android这些系统镜像文件是存储在nand flash中的,然后每个芯片都有个boot rom,在上电时刻,boot rom开始启动,boot rom加载preloader到内部SRAM中,preloader被加载完成之后,程序就从boot
rom跳转到preloader处开始执行,preloader初始化好外部RAM之后,preloader将lk(或uboot)加载外部RAM中,然后跳转到lk(或uboot)中去执行,lk(或uboot)紧接着就加载bootimage(包括kernel和ramdisk)到外部RAM中,然后去执行kernel部分。



1.1BootRom

ROM code是芯片厂商直接烧写到芯片中。

(1)  设备上电后,Boot ROM开始运行。

(2)  BootROM初始化软件堆栈(software stack)、通信端口和可引导存储设备(比如NAND/EMMC)。

(3)  BootROM通过UART/USB和flash工具握手。

(4)  BootROM通过UART下载pre-loader镜像到NANDflash/EMMC中,然后重启。

(5)  BootROM加载pre-loader到内部SRAM汇总,因为DRAM还没有初始化。

(6)  BootROM跳转到pre-loader并执行。

1.2 BootLoader

BootLoader程序也有多种类型,不同的BootLoader程序,其引脚参数不同。



(1) SD方式

(2) NorFlash Rom方式

(3) NandFlash Rom + chip方式

       一般情况下,发布的正式版本,引脚参数都是固定的,是不可改变的。

1.2.1 preLoader

preloader也就是BootLoader的第一部分。

       pre-loader是内置的loader,它的主要功能如下:

(1)  负责在芯片组平台(chipset platform)上准备好可执行的环境

(2)  如果外部工具有效,它会试图通过UART或是USB来和外部工具握手。(比如USB升级)

(3)  从NAND/EMMC加载U-Boot,并跳转到U-Boot。

(4)  使用工具握手,设备能够触发进入下载模式来下载需要的镜像,或是进入工厂/测试模式,比如META模式和ATE工厂模式,在这些模式下可以测试模块,或是通过传递引导参数给U-Boot和linux内核来校准设备(devicecalibration)

1.2.2 U-Boot

U-Boot也就是BootLoader的第二部分。

 

1) 初始化本阶段使用的硬件设备

2) 检测系统内存映射

3) 将内核从Flash读取到RAM中

4) 为内核设置启动参数

       U-Boot在执行过程中必须设置和初始化 Linux 的内核启动参数。Linux内核在启动过程中会根据该启动参数进行相应的初始化工作。

5) 调用内核映像

       U-Boot完成的最后一项工作便是调用 Linux内核。如果 Linux 内核存放在 Flash 中,并且可直接在上面运行(这里的 Flash指 Nor Flash),那么可直接跳转到内核中去执行。但由于在 Flash 中执行代码会有种种限制,而且速度也远不及
RAM 快,所以一般的嵌入式系统都是将 Linux内核拷贝到 RAM 中,然后跳转到 RAM 中去执行。不论哪种情况,在跳到 Linux 内核执行之前 CUP的寄存器必须满足以下条件:r0=0,r1=处理器类型,r2=标记列表在 RAM中的地址。

智能终端在该阶段可能做了更多动作。

1.3 kernel

start_kernel是所有 Linux 平台进入系统内核初始化后的入口函数,它主要完成剩余的与硬件平台相关的初始化工作,在进行一系列与内核相关的初始化后,调用第一个用户进程-init
进程并等待用户进程的执行,这样整个 Linux 内核便启动完毕。该函数所做的具体工作有:

       1) 调用 setup_arch()函数进行与体系结构相关的第一个初始化工作;

对不同的体系结构来说该函数有不同的定义。对于 ARM 平台而言,该函数定义在arch/arm/kernel/Setup.c。它首先通过检测出来的处理器类型进行处理器内核的初始化,然后通过 bootmem_init()函数根据系统定义的 meminfo 结构进行内存结构的初始化,最后调用paging_init()开启 MMU,创建内核页表,映射所有的物理内存和 IO空间。

       2) 创建异常向量表和初始化中断处理函数;

       3) 初始化系统核心进程调度器和时钟中断处理机制;

       4) 初始化串口控制台(serial-console);

ARM-Linux 在初始化过程中一般都会初始化一个串口做为内核的控制台,这样内核在启动过程中就可以通过串口输出信息以便开发者或用户了解系统的启动进程。

       5) 创建和初始化系统 cache,为各种内存调用机制提供缓存,包括;动态内存分配,虚拟文件系统(VirtualFile System)及页缓存。

       6) 初始化内存管理,检测内存大小及被内核占用的内存情况;

       7) 初始化系统的进程间通信机制(IPC);

       当以上所有的初始化工作结束后,start_kernel()函数会调用 rest_init()函数来进行最后的初始化,包括创建系统的第一个进程-init 进程来结束内核的启动。Init 进程首先进行一系列的硬件初始化,然后通过命令行传递过来的参数挂载根文件系统。最后init
进程会执行用 户传递过来的“init=”启动参数执行用户指定的命令,或者执行以下几个进程之一:

execve("/sbin/init",argv_init,envp_init);

execve("/etc/init",argv_init,envp_init);

execve("/bin/init",argv_init,envp_init);

execve("/bin/sh",argv_init,envp_init)。

       当所有的初始化工作结束后,cpu_idle()函数会被调用来使系统处于闲置(idle)状态并等待用户程序的执行。至此,整个 Linux 内核启动完毕。

1.4 Init

init命令是Linux下的进程初始化工具,init进程是所有Linux进程的父进程,它的进程号为1。init命令是Linux操作系统中不可缺少的程序之一,init进程是Linux内核引导运行的,是系统中的第一个进程。

1.4.1 /etc/inittab

作为系统的第一个执行的程序“/sbin/init”。init程序做的工作相当多,除了利用设置文件“/etc/inittab”来获取运行等级之外,还会通过运行等级的设置值启动不同的服务项目。运行等级是指linux通过设置不同等级来规定系统用不同的服务来启动,让linux的使用环境不同。

"/etc/inittab"中有这么一句" si::sysinit:/etc/init.d/rcS",表明系统需要主动使用"rcS"这个shell脚本来设置系统环境。但这个文件的文件名在各个版本中基本上都是有区别的。

# /etc/inittab: init(8)configuration.
# $Id: inittab,v 1.91 2002/01/2513:35:21 miquels Exp $ # The default runlevel.
id:3:initdefault: 1:012345:respawn:/sbin/getty -n -LttyMT0 115200 vt100 -l /bin/sh # Boot-time systemconfiguration/initialization script.
# This is run first except whenbooting in emergency (-b) mode.
si::sysinit:/etc/init.d/rcS

1.4.2 rcS

1.  source/etc/profile

2.  挂载 fstab 基本的文件系统 (/, proc, sys, devpts, tmpfs…)

3.  然后转 rc.local

#! /bin/sh
#设置环境变量
source /etc/profile # Don't use scripts. Just use mount-a for fast boot.
/bin/mount-avt nonfs,nosmbfs #if [ -e /etc/readahead_early ];then
# echo Start readahead /etc/readahead_early
# busybox readahead `cat /etc/readahead_early` &
#fi # Run /etc/rc.d/rc.local if it exists
[ -x /etc/rc.d/rc.local ] &&/etc/rc.d/rc.local

1.4.3 用户自定义引导程序(/etc/rc.d/rc.local)

一般来说,自定义的程序不需要执行上面所说的繁琐的建立shell增加链接文件的步骤,只需要将命令放在rc.local里面就可以了,这个shell脚本就是保留给用户自定义启动内容的。

1.  设置终端参数 stty

2.  设置基本网络相关参数 (lo, hosts, resolv.conf, …)

......

系统启动 之 Linux系统启动概述(1)的更多相关文章

  1. 系统启动 之 Linux系统启动概述(2)

    博客:http://blog.csdn.net/younger_china/article/details/51615916 Linu系统启动是一个"冗长乏味"的过程,那么我们现就 ...

  2. Linux 入门记录:十八、Linux 系统启动流程 + 单用户修改 root 密码 + GRUB 加密

    一.系统启动流程 一般来说,Linux 系统的启动流程是这样的: 1. 开机之后,位于计算机主板 ROM 芯片上的 BIOS 被最先读取,在进行硬件和内存的校验以及 CPU 的自检没有异常后, BIO ...

  3. Linux系统启动那些事—基于Linux 3.10内核【转】

    转自:https://blog.csdn.net/shichaog/article/details/40218763 Linux系统启动那些事—基于Linux 3.10内核 csdn 我的空间的下载地 ...

  4. Linux系统启动详解(一)

    本篇主要以Centos为例,讲述整个Linux系统启动过程,包括了grub引导,initramfs流程,/sbin/init执行rc.sysinit及rc的大体流程. 另外,本篇有一个实例来说明,将整 ...

  5. 学习笔记:CentOS7学习之十八:Linux系统启动原理及故障排除

    目录 学习笔记:CentOS7学习之十八:Linux系统启动原理及故障排除 18.1 centos6系统启动过程及相关配置文件 18.1.1 centos6系统启动过程 18.1.2 centos6启 ...

  6. Linux学习之CentOS(二十一)--Linux系统启动详解

      在这篇随笔里面将对Linux系统的启动进行一个详细的解释!我的实验机器是CentOS6.4,当然对于现有的Linux发行版本,其系统的启动基本上都是一样的! 首先我们来看下Linux系统启动的几个 ...

  7. linux基础-附件1 linux系统启动流程

    附件1 linux系统启动流程 最初始阶段当我们打开计算机电源,计算机会自动从主板的BIOS(Basic Input/Output System)读取其中所存储的程序.这一程序通常知道一些直接连接在主 ...

  8. Linux系统启动过程分析

    [原创]Linux系统启动过程分析-wjlkoorey258-ChinaUnix博客http://blog.chinaunix.net/uid-23069658-id-3142047.html 经过对 ...

  9. Linux系统启动流程及安装命令行版本

    Debian安装 之前也安装过很多次linux不同版本的系统,但安装后都是直接带有桌面开发环境的版本,直接可以使用,正好最近项目不是很忙,想一直了解下Linux的整个启动流程,以及如何从命令行模式系统 ...

随机推荐

  1. python + selenium <一>

    python 安装 python 下载地址: http://python.org/getit/ ez_setup.py 下载地址: https://pypi.python.org/packages/s ...

  2. JS Math.round()方法原理

    请先测试代码: <!doctype html> <html lang="en"> <head> <meta charset="U ...

  3. python多版本的pip共存问题解决办法

    python pip 多版本 问题情景 最开始学python的时候用的是py2,且一直用pip来安装库函数.后来py3出来了,所以就装上了,但是一装上出问题了,主要有两个主要的问题.下面将详细说明. ...

  4. Sql(in与exists)

    1.如果查询的两表大小相当,那么用in和exists差别不大,如果两个表中一个较小一个较大,则子查询表小的用exists,子查询表大的用in. 2.not in逻辑上不完全等同于not exists, ...

  5. 机器学习:Python实现最小均方算法(lms)

    lms算法跟Rosenblatt感知器相比,主要区别就是权值修正方法不一样.lms采用的是批量修正算法,Rosenblatt感知器使用的 是单样本修正算法.两种算法都是单层感知器,也只适用于线性可分的 ...

  6. Web前端面试指导(十四):如何居中一个元素(正常、绝对定位、浮动元素)?

    题目点评 这道题目的提问比较多,连续问了三个问题,正常元素.绝对定位元素.互动元素如何居中,而且居中没有说清楚是垂直居中还是水平居中,要回答清楚这个问题,必须得有深厚的功底,而且要分类的来回答,条理要 ...

  7. Android注解使用之Dagger2实现项目依赖关系解耦

    前言: 最近牵头发起公司app的重构工作,如何通过重构让项目的耦合降低.开发效率提高,一直是我努力的方向,今天来学习一下一个注解框架Dagger2,然后看看如何使用它来降低项目的耦合. Dagger2 ...

  8. 自动化监控利器-Zabbix深入配置和使用

    1.  配置流程 Zabbix完整的监控配置流程可以简单描述为: Host groups(主机组)→Hosts(主机)→Applications(监控项组)→Items(监控项)→Triggers(触 ...

  9. POST和GET的详细解释以及区别

    Http定义了与服务器交互的不同方法,最基本的方法有4种,分别是GET,POST,PUT,DELETE.URL全称是资源描述符,我们可以这样认为:一个URL地址,它用于描述一个网络上的资源,而HTTP ...

  10. Linux开机启动(bootstrap)上

    Linux开机启动(bootstrap)   作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 计算机开机是一个神秘的过程.我们只是 ...