arm linux系统启动流程
来源:互联网 发布:ios手游源码 编辑:程序博客网 时间:2024/06/05 00:31
面试中经常遇到此类问题arm linux系统启动流程,首先我们遇到此类问题必须明白题目所要考察我们的目的是什么:
1:考察点:在嵌入式开发中,遇到linux或Android系统启动报错时确定问题的位置,快速定位并解决问题。
2:问题所涉及到的知识点有:Bootloader、Linux和Android的系统启动流程。
3:解答思路:
首先需要我们清楚整体的嵌入式移植开发流程图:
一、Boot启动流程
U-Boot启动内核的过程可以分为两个阶段,两个阶段的功能如下:
(1)第一阶段主要包含依赖于CPU的体系结构硬件初始化的代码,通常都用汇编语言来实现。
硬件设备初始化(屏蔽所有的中断、设置CPU的速度和时钟频率、RAM初始化、初始化LED、关闭CPU内部指令/数据Cache等)
把Bootloader 为第二阶段准备RAM空间。
复制Bootloader的第二阶段代码到RAM空间中。
设置堆栈
跳转到第二阶段的C程序入口点
(2)第二阶段的功能
初始化本阶段使用的硬件设备
检测系统内存映射
将内核映像和根文件系统映像从Flash读到RAM
为内核设置启动参数
调用内核
代码如下:
第一阶段:主要是汇编代码①进入arch/arm/cpu/armv7/start.S 直接在物理地址执行(uImage中)⑴建立中断异常向量表39 _start: b reset ||\/127 bl save_boot_params 保存了当前cpu的运行状态,reset则进行跳转⑵设置svc模式131 mrs r0, cpsr132 bic r0, r0, #0x1f133 orr r0, r0, #0xd3134 msr cpsr,r0 设置向量,为设置协处理器做准备167 bl cpu_init_cp15 完成了我们对协处理器设置,⑶关闭了MMU和cache ||\/168 bl cpu_init_crit || \/ b lowlevel_init(②board/samsung/fs4412/lowlevel_init.S ) 设置了reset,使能reset ⑷关闭了开门狗(不需要帮我们重启,为了观察现象) ⑸ 初始化时钟,⑹初始化内存,进行判断uboot是否运行在物理地址中TEXT_BASE (0x43e000000) 进行⑺串口初始化操作,我们已经可以使用串口显示 push {lr} ..... pop {pc} ==> mov pc,lr bl _main(③arch/arm/lib/crt0.S ) ⑻初始化堆栈 ,准备启动C语言 为gd结构体的赋值做准备(提供gd结构体大小的空间) || \/ 115 bl board_init_f (④arch/arm/lib/board.c ) ⑼ 给gd结构体进行赋值 gd结构体定义(⑤include/asm/global_data.h ) 303 for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { 304 if ((*init_fnc_ptr)() != 0) { 305 hang (); 306 } 307 } 完成各种板子初始化操作,最重要的是初始化了DRAM控制器,我开始使用400000000-800000000物理地址第二阶段:主要是c代码 回到arch/arm/lib/crt0.S 进行寄存器赋值 r8 = gd->start_addr_sp lr = here r0 = gd->start_addr_sp u-boot起始地址 r2 = gd->relocaddr 搬移地址||\/b relocate_code(⑥arch/arm/cpu/armv7/start.S)196 copy_loop:197 ldmia r0!, {r9-r10} /* copy from source address [r0] */ 进行循环搬移198 stmia r1!, {r9-r10} /* copy to target address [r1] */199 cmp r0, r2 /* until source end address [r2] */200 blo copy_loop 条件跳转 成立条件是cmp不相等⑽自搬移关键代码243 bx lr(链接寄存器) 跳转 || \/ arch/arm/lib/crt0.S ⑾ 清除bss段 从bss_start到bss_end (物理地址在System.map中) 目的:腾出内存空间 167 ldr pc, =board_init_r || \/ arch/arm/lib/board.c ⑿进行最后的初始化操作,开始执行uboot引导系统⒀ 702 for (;;) { 703 main_loop(); 704 } || \/ ⑦ common/main.c 获取用户设置的bootcmd等参数,执行uboot
二、arm linux内核启动流程
第一阶段:内核的重定位和内核的自解压
第二阶段:执行没有压缩的内核的汇编代码部分
获取CPU信息
检查平台设备号
创建页表
打开MMU
清除BBS段
执行内核C语言部分入口函数
第三阶段:
获取uboot给内核传递的参数
控制台初始化
执行init命令
挂载文件系统
执行用户控件的第一个程序
代码如下:
①进入arch/arm/kernel/head.S使能thumb指令集,我们可以使用thumb指令,启动了异常处理机制 92 safe_svcmode_maskall r9 使能svc模式 365 mrc p15, 0, r9, c0, c0 @ get processor id 95 bl __lookup_processor_type || \/ r4 = 178行虚拟地址 r5 = begin r6 = end ②arch/arm/kernel/head-common.S 进行物理地址和虚拟地址转换,判断处理器类型 148 * r3, r4, r6 corrupted 149 * r5 = proc_info pointer in physical address space 50 * r9 = cpuid (preserved) 118 * r1 = machine no, r2 = atags or dtb,119 * r8 = phys_offset, r9 = cpuid, r10 = procinfo 121 bl __vet_atags || \/ arch/arm/kernel/head-common.S 完成了对设备传参方式的验证(46-50设备树传参)123 bl __fixup_smp124 #endif125 #ifdef CONFIG_ARM_PATCH_PHYS_VIRT126 bl __fixup_pv_table 127 #endif进行处理器信息保存,为创建页表做准备128 bl __create_page_tables 创建页表(创建在物理地址)arch/arm/mm/proc-v7.S进行armv7处理器的设置1、开启了cache,tlbs2、开启clk3、设置了reset414 * r0 = cp#15 control register415 * r1 = machine ID416 * r2 = atags or dtb pointer417 * r4 = page table (see ARCH_PGD_SHIFT in asm/memory.h)418 * r9 = processor ID419 * r13 = *virtual* address to jump to upon completion使能mmu需要将页表的物理地址位置指向虚拟地址,我们保存在协处理器中444 b __turn_mmu_on 完成开启mmu操作使能成功mmu进行地址转换前需要进行mmu使能137 ldr r13, =__mmap_switched @ address to jump to after138 @ mmu has been enabled || \/ 81 adr r3, __mmap_switched_data(类似于这样的adr操作,都是从处理器或者uImage获取到的) 104 b start_kernel || \/ ③init/main.c 进行各种初始化操作 setuparch()保存了uboot传递的参数,保存在machine(arch/arm/include/asm/mach/arch.h ) 652 rest_init(); 382 kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND); 840 kernel_init_freeable(); 928 prepare_namespace(); || \/ ④ init/do_mounts.c 589 mount_root(); 进行文件系统判断 mount_nfs_root()完成了对文件系统的挂载内核启动:head.S head-common.S init/main.c init/do_mount.c
三、Android启动流程:
Init进程是Linux内核启动后创建的第一个用户进程,地位非常重要,Init进程在初始化过程中会启动很多重要的守护进程,因此,了解Init进程的启动过程将有助于我们更好的理解Android系统。Init除了完成系统的初始化之外,本身也是一个守护进程,负担着系统部分很重要的职责。
知识点:介绍Init进程的初始化以及它作为守护进程的功能。
在介绍Init进程前,我们先简单介绍Android的启动过程。从系统角度看,Android的启动过程可分为bootloader引导,装载和启动Linux内核,启动Android系统,3个大的阶段。其中Android系统的启动还可以细分为启动Init进程,启动zygote,启动SystemService,启动serviceManager,启动Home等多个阶段
1)bootloader引导
当我们按下手机的电源键,最先运行的就是bootloader.bootloader主要的作用是初始化基本的硬件设备(如CPU,内存,Flash等)并且通过建立内存空间映射,为装载Linux内核准备好合适的运行环境.一旦Linux内核装载完毕,bootloader将会从内存中清除掉.
如果用户在Bootloader运行期间,按下预定义的组合键,可以进入系统的更新模块.Android的下载可以选择进入FastBoot模式和Recovery模式.
Fastboot是Android设计的一套通过USB来更新手机分区映像的协议(绕写分区镜像),方便开发人员能快速更新制定的手机分区.但是一般的零售机往往去掉了Fastboot,Google销售的开发机则带有Fastboot模块.
Recovery模式是Android 特有的升级系统.利用Recovery模式,手机可以进行回复出厂设置,或者执行OTA,补丁和固件升级.进入Recovery模式实际上是启动了一个文本模式的Linux.
2) 装载和启动Linux内核.
Android的boot.img存放的就是Linux内核(system.img)和一个根文件系统(ramdisk.img).Bootloader会把boot.img映像装载进内存.然后Linux内核会执行整个系统的初始化,完成后装载根文件系统,最后启动Init进程.
3) 启动Init进程.
Linux内核加载完毕后,会首先启动Init进程,Init进程是系统的第一个进程.在Init进程的启动过程中,会解析Linux的配置脚本init.rc文件(脚本规则).根据init.rc文件的内容,init进程会装载Android的文件系统,创建系统目录(adb shell 系统目录),初始化属性系统(进程全局变量),启动Android系统重要的守护进程(后台进程),这些进程包括USB守护进程,adb守护进程(debug桥),vold守护进程(外部存储,检测热插拔sd卡(EXT4文件系统),检测挂载),rild守护进程(电话卡)等.
最后Init进程也会作为守护进程来执行修改属性请求,重启崩溃的进程等操作.
4) 启动serviceManager((本地层)进程)和四大组件没有关系
ServiceManager由Init进程启动.它主要的作用是管理Binder服务,负责Binder服务的注册与查找.
5)启动zygote进程.(受精卵)--------》(之后是java进程)
Init进程初始化结束时,会启动zygote进程.zygote进程负责fork出应用进程(复制整个父进程数据),是所有应用进程的父进程.zygote进程初始化时会创建Dalivik虚拟机(运行java程序),预装载系统的资源文件(Button,farmwork和库资源)和Java类.所有从Zygote进程fork出的用户进程(app应用程序)将继承和共享这些预加载的资源,不用浪费时间重新加载,加快了应用程序的启动过程.启动结束后,zygote进程也将变为守护进程,负责响应启动APK应用程序的请求(提高运行效率,预加载)
6) 启动SystemServer.
SystemServer是zygote进程fork出的第一个进程,也是整个Android系统的核心进程.在SystemServer中运行着Android系统大部分的Binder服务.SystemServer首先启动本地服务SensorService(传感器);接着启动包括 ActivityManagerService (四大组件之activity底层实现),WindowsManagerService(APP窗口),PackageManagerService(包管理)在内的所有Java服务. (接口API通过Launcher调用)
7)启动MediaServer(摄像头,音视、频服务)
MediaServer由Init进程启动.它包含了一些多媒体相关的本地BInder服务,包括:cameraService,AudioFlingerService,MediaPlayerService和AudioPolicyService.
8) 启动Launcher(桌面)(java代码写的)
SystemServer加载完所有Java服务后,最后会调用ActivityManagerService的SystemReady()方法.在这个方法的执行中,会发出Intent "android.intent.category.HOME".凡是相应这个Intent的apk应用都会运行起来,Launcher应用是Android系统默认的桌面应用,一般只有它会相应这个Intent,因此,系统开机后,第一个运行的应用就是Launcher.
- ARM Linux系统启动流程
- arm linux系统启动流程
- ARM-Linux嵌入式系统启动流程
- ARM 平台上的Linux系统启动流程
- ARM 平台上的Linux系统启动流程
- ARM+Linux系统启动流程分析----ARM处理器的启动流程
- ARM+Linux系统启动流程分析----系统启动总概述
- Linux双核SMP系统启动流程(Zynq-ARM-CortexA9)
- ARM+Linux系统启动流程分析----bootloader初始化系统
- linux系统启动流程
- linux系统启动流程
- Linux系统启动流程
- Linux 系统启动流程
- Linux系统启动流程
- Linux系统启动流程如下
- linux系统启动流程分析
- linux系统启动流程
- Linux系统启动流程
- MySQL PHP 语法
- File类
- List和Set学习总结
- 开通博客的第一天
- Linux基础(4)
- arm linux系统启动流程
- 数据类型2-C语言学习笔记5
- Jalangi2 中文API
- Java IO流之File文件类的使用
- 循环队列的相关操作
- cocos 寻路 c++实现
- 在Struts1.x中用actionForm实现 request.getParameterValues("")效果;
- File
- Spark学习笔记@第一个例子wordcount+Eclipse