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

        随着智能终端功能的愈来愈庞大,与之,硬件配置愈来愈高,开机时间却愈来愈长。人们在享受强大功能的同时,对冗长的智能终端的开机时间却愈来愈缺少耐心。
为了“取悦”用户,须要提供较好的用户体验,那么就必须使得智能终端尽量短的进入“可工做”状态。
       本文中的“尽量短的开机时间”,“开机优化”、“开机时间优化”均表示同一个意思。
       若是计划对linux系统进行开机时间优化,那么就必须熟悉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部分。


android

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并执行。

shell

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, …)

......框架

相关文章
相关标签/搜索