linux-kernel 启动过程 一

概述

前边的章节我们分析了UBOOT是怎么加载内核的,最终是通过bootz等指令跳转到了一个地址,就开始进入到内核,要分析内核的起始点也是得先从链接脚本开始分析,因此我们先编译下内核,然后从链接脚本开始分析(注:内核版本4.1.15,后续系列均为此版本)

1、内核目录结构及编译

1.1 内核编译

  1 #!/bin/sh                                                                       
  2 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
  3 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_alientek_emmc_defconfig
  4 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
  5 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j16
  • 首先clean下工程,删除无用配置
  • 然后选择一个配置文件来进行编译,跟uboot类似,配置文件位置在arch/arm/configs/
  • 然后make menuconfg 图形化界面进行内核配置
  • 最后make 进行编译

1.2 内核目录结构

在这里插入图片描述

  • arch:架构有关的目录,比如 arm、 arm64、 avr32、 x86 等等架构。
  • block:块设备目录,像 SD 卡、 EMMC、 NAND、硬盘等存储设备就属于块设备
  • COPYING:版权声明
  • crypro:加密相关,比如常见的 crc、 crc32、 md4、 md5、 hash 等加密算法
  • Documentation:此目录里面存放着 Linux 相关的文档,如果要想了解 Linux 某个功能模块或驱动架构的功能,就可以在 Documentation 目录中查找有没有对应的文档。
  • drivers:驱动相关,根据驱动类型的不同,分门别类进行整理,比如 drivers/i2c 就是 I2C相关驱动目录, drivers/gpio 就是 GPIO 相关的驱动目录,这是学习的重点
  • firmware:固件相关,用于存放固件
  • fs:文件系统相关,存放文件系统,比如 fs/ext2、 fs/ext4、 fs/f2fs 等
  • include:头文件相关
  • init:初始化相关,内核启动的时候初始化代码
  • ipc:进程间通讯相关
  • Kbuild:Makefile 会读取此文件
  • Kconfig:图形化配置界面的配置文件
  • kernel:内核相关
  • lib:库文件,一些公用的库函数
  • MAINTAINERS:维护者名单
  • Makefile:linux顶层makefile
  • make_mx6ull_alpha_emmc.sh:笔者加的编译脚本
  • mm:内存管理文件
  • modules.* Modules.* :一系列文件,和模块有关,编译生成的文件
  • net:网络相关文件
  • README:Linux 描述文件,详细讲解了如何编译 Linux 源码,以及 Linux 源码的目录信息
  • REPORTING-BUGS: BUG 上报指南
  • samples:例程相关
  • scripts:脚本相关,Linux 编译的时候会用到很多脚本文件,这些脚本文件就保存在此目录
  • security:安全相关
  • sound:音频处理相关,音频驱动文件并没有存放到 drivers 目录中,而是单独的目录
  • System.map:符号表,编译生成的文件
  • tools:工具相关,存放一些编译的时候使用到的工具
  • usr:与 initramfs 相关的目录,用于生成initramfs
  • virt:提供虚拟机技术(KVM),存放虚拟机相关文件
  • vmlinux:编译出来的、未压缩的 ELF 格式Linux 文件,编译生成
  • vmlinux.dis:vmlinux的反汇编文件,编译生成
  • vmlinux.o:vmlinux的obj文件,编译生成

此外还有部分隐藏文件,列举几个比较重要的:

  • .config文件:跟 uboot 一样, .config 保存着 Linux 最终的配置信息,编译 Linux 的时候会读取此文件中的配置信息。最终根据配置信息来选择编译 Linux 哪些模块,哪些功能,编译生成
  • .vmlinux.cmd:cmd 文件,用于连接生成 vmlinux

编译生成的image文件保存在arch/arm/boot,如下
在这里插入图片描述
注:Image是编译生成的内核镜像二进制文件,ZImage是将Image进行了压缩的,通常使用的也是ZImage。

2、启动流程

2.1 链接脚本vmlinux.lds

首先分析 Linux 内核的连接脚本文件 arch/arm/kernel/vmlinux.lds,通过链接脚本可以找到 Linux 内核的第一行程序是从哪里执行的,如下
在这里插入图片描述
我们就看关键的一些信息,ENTRY指定了入口函数,即stext(链接指定入口点的几个方式,在其他的bolg中有介绍)。

2.2 入口函数stext

stext 定义在文件arch/arm/kernel/head.S中,如下
在这里插入图片描述
首先说明了在进入到kernel的入口函数之前要关闭mmu,D-cache,同时stext的入口参数有3个,第一个是0,第二个机器id,第三个是设备树的地址(此地址为物理地址)。
在这里插入图片描述

  • 第81行:设置为大端模式,其实ARM_BE8是个宏,定义在arch/arm/include/asm/assembler.h,如下
    在这里插入图片描述
    如上图,arm是支持修改大小端的,默认是小端,因此如果需要修改成大端则会执行指令 setend be,将其设置为大端模式
  • 第83~86行:切换到thumb指令集
  • 第88~90行:若启动了虚拟化,此处未启用
  • 第92行:调用函数safe_svcmode_maskall,定义在arch/arm/include/asm/assembler.h中,确保CPU 处于 SVC 模式,并且关闭了所有的中断
  • 第94行:从cp15协处理器的c0寄存器读取硬件的CPU ID号,保存在r9中
  • 第95行:调用函数__lookup_processor_type,检查当前系统是否支持此 CPU,如果支持的就
    获 取 procinfo 信 息,会将其保存到 r5 寄存器中 。 procinfo 是 proc_info_list 类 型 的 结 构 体 , proc_info_list 在 文 件
    arch/arm/include/asm/procinfo.h 中的定义如下
    在这里插入图片描述
  • 第96~98行:若获取到的cpu信息为0,则跳转到__error_lpae,最终死循环
  • 第100~106行:若定义3级页表才需要,此处未定义

在这里插入图片描述

  • 第108~115行:未定义XIP,需要计算出物理地址和虚拟地址的差值。
  • 第121行:校验uboot给内核的传参ATAGS(r2)格式是否正确,定义在arch/arm/kernel/head-common.S
  • 第122~124行:多核的一些检测
  • 第125~127行:给物理地址打补丁,转换成虚拟地址
  • 第128行:调用函数__create_page_tables 创建页表,以便后续打开mmu

注:linux内核本身被链接在虚拟地址处,因此kernel希望尽快建立页表并且启动MMU进入虚拟地址工作状态,但是kernel本身工作起来后页表体系是非常复杂的,建立起来也不是那么容易的。因此kernel想了一个好办法,就是:建立页表分两步走。第一步,kernel先建立一个段式页表(和uboot之前建立的页表一样,页表以1MB为单位来区分的),这里的函数就是建立段式页表。段式页表本身比较好建立(段式页表1MB一个映射,4GB的空间需要4096个页表项,每个页表项4字节,因此一共需要16KB内存来做页表),坏处是比较粗不能精细管理内存;第二步,再去建立一个细页表(以4KB为单位),然后启动新的细页表,废除第一步建立的段式映射页表。
在内核启动的早期,建立的段式页表,并在内核启动的前期使用;在内核启动的后期,就会再次建立细页表并启用。等内核启动工作起来之后就只有细页表了。

在这里插入图片描述

  • 第137行:取得__mmap_switched的链接地址,保存在r13中(此时mmu未开启,无法跳转到该地址运行)
  • 第139行:将1f处的地址保存到lr寄存器中,即lr地址是__enable_mmu
  • 第140行:将上文计算的r4(PHYS_OFFSET - PAGE_OFFSET)存储到r8中
  • 第141行:把cpu对应proc info中的__cpu_flush存放到r12寄存器中,r10存储的是cpuinfo(这个__cpu_flush成员存放的是cpu对应架构的setup函数的地址)
  • 第142行:与r10相加后,的得setup函数的物理地址
  • 第143行:执行setup函数,定义在arch/arm/mm/proc-v7.s中,主要是一些打开mmu之前的准备工作, 执行完之后就跳转到__enable_mmu函数

在这里插入图片描述

  • 第429~433行:根据配置使能或禁止地址对齐错误检测
  • 第434~436行:根据配置使能或禁止数据cache
  • 第437~439行:控制位选择淘汰算法
  • 第440~442行:根据配置使能或禁止指令cache
  • 第443~448行:设置访问权限
  • 第449行:设置页表地址c2
  • 第451行:调用了__turn_mmu_on打开mmu
    在这里插入图片描述
  • 第472行:指令同步屏障
  • 第473行:根据配置设置SCTLR寄存器,打开mmu使能位,cache等
  • 第477~478行:由于mmu已经使能,因此这里可以运行虚拟地址的函数了,跳转到__mmap_switched

__mmap_switched函数定义在arch/arm/kernel/head-common.S 中,函数代码如下:
在这里插入图片描述

  • 第82行:加载__mmap_switched_data的地址到r3中

  • 第84行:设置寄存器值,如下在这里插入图片描述
    相当于R4=_data_loc(数据存放的位置),R5=_sdata(是数据开始的位置),R6=__bss_start(bss开始的位置),R7=_end(bss结束的位置, 也是内核结束的位置)

  • 第85~89行:比较R4和R5,判断数据存储的位置和数据的开始的位置是否相等,如果不相等,则需要搬运数据,从 __data_loc 将数据搬到 _sdata. 其中 __bss_start 是bss的开始的位置,也标志了 data 结束的位置,因而用其作为判断数据是否搬运完成

  • 第91行:初始化栈基指针fp

  • 第92~94:清空bss段数据

  • 第96行:重新设置寄存器值

  • R4=processor_id(cpu处理器ID地址,其变量定义在arch/arm/kernel/setup.c中)

  • R5=__machine_arch_type(machine id地址,其变量定义在arch/arm/kernel/setup.c中)

  • R6=__atags_pointer(dtb指针的地址,其变量定义在arch/arm/kernel/setup.c中)

  • R7=cr_alignment(cp15的c1寄存器的值的地址,也就是mmu控制寄存器的值,其变量定义在arch/arm/kernel/entry-armv.S中)

  • sp=init_thread_union + THREAD_START_SP(init_thread_union可在System.map中获取,笔者的是0x809e6000,这样一来相当于SP的初值是0x809e6000 + 0x2000 - 8)

  • 第97~98行:thumb指令的实现,意义同第86行,同时只有一处生效

  • 第99行:把cpu处理器id(r9)放到processor_id变量中

  • 第100行:把mechine id(r1)存放到__machine_arch_type变量中

  • 第101行:把dtb的地址指针(r2)存放到__atags_pointer变量中(此地址为物理地址,使用需转换)

  • 第102~103行:把cp15的c1的寄存器的值(r0)存放到cr_alignment变量中

  • 第104行:跳转到start_kernel开始启动内核

晴天晴天天天天
关注 关注
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
[kernel 启动流程] (第一章)概述
ooonebook的博客
09-30 1万+
建议先参考《[kernel 启动流程] 前篇——vmlinux.lds分析》等文章。一、kernel启动之前的准备动作在kernel启动之前的准备都是由bootloader来完成。所以不管是什么bootloader,例如uboot、LK、superboot等等,都需要实现以下准备动作。这里指说明概念,不涉及代码。 我们在project X项目中使用的bootloader是uboot,具体代码参考第
内核启动流程——init进程分析
主要记录嵌入式学习与开发过程。
05-04 6716
以下内容源于朱有鹏嵌入式课程的学习与整理,如有侵权请告知删除。
科普文:图文探究Linux内核
最新发布
为无为,事无事,味无味。
07-25 1866
本文主要讲解什么是Linux内核,以及通过多张图片展示Linux内核的作用与功能,以便于读者能快速理解什么是Linux内核,能看懂Linux内核。拥有超过1300万行的代码,Linux内核是世界上最大的开源项目之一,但是内核是什么,它用于什么?
linux kernel启动流程
weixin_33797791的博客
01-08 303
linux kernel启动是从./init/main.c中开始的,其大概流程是: 1. 调用start_kernel()函数; 2. start_kernel()调用rest_init()函数; 3. rest_init()调用kernel_init()函数; 4. kernel_init()调用init_post()函数; 5. init_post()调用run_init_process()函...
linux内核启动流程
jinghuainfo
08-23 537
Linux内核启动流程 arch/arm/kernel/head-armv.S 该文件是内核最先执行的一个文件,包括内核入口ENTRY(stext)到start_kernel间的初始化代码,主要作用是检查CPU ID, Architecture Type,初始化BSS等操作,并跳到start_kernel函数。在执行前,处理器应满足以下状态: r0 - should be 0 r1 - u...
Linux内核】启动流程——Kernel 启动流程梳理
Ethan-Code's blog
02-11 1882
uboot将控制权交给 kernelkernel入口为 stext,主要完成验证是否支持此 CPU、验证 uboot 传入的设备树(dtb)合法性、使能 MMU 等工作,最终会调用 C 函数 start_kernel()相当于内核的 main 函数,内核的生命周期就是从执行这个函数的第一条语句开始的,直到最后一个函数 reset_init(),内核将不再从这个函数中返回。 本文详解了kernel启动流程中涉及到的重要函数,并添加printk打印log验证。
Linux:内核kernel启动流程
weixin_44498318的博客
06-10 1863
1. Linux启动流程框图 ENTRY(stext) (arch/arm/kernel/head.S) |_ safe_svcmode_maskall (arch/arm/include/asm/assembler.h) |_ __lookup_processor_type (arch/arm/kernel/head-common.S) |_ __vet_atags (arch/arm/kernel/head-common.S) |_ __create_page_tables (arch/arm/
OpenNuvoton-NUC970-Linux-Kernel-master
04-08
标题“OpenNuvoton-NUC970-Linux-Kernel-master”暗示了这是一个与OpenNuvoton NUC970系列微处理器相关的Linux内核源代码仓库的主分支。这个描述“OpenNuvoton-NUC970_Linux_Kernel-master”进一步确认了这一点,...
linux-kernel-howto.rar_KERNEL-HOWTO._Linux Kernel How_linux_linu
09-19
"Linux-kernel-howto.rar"中的"KERNEL-HOWTO_Linux Kernel How_linux_linu"文档详细介绍了这一过程,本文将基于这份文档,为你揭示Linux内核裁剪的奥秘。 Linux内核裁剪的主要目的是减少内核的大小,提高系统性能,...
Linux-kernel-configure.rar_linux kernel_linux 内核_linux 内核 配置_lin
09-21
1. **内核配置简介**:Linux内核配置是根据特定硬件需求和系统优化目标,定制内核的过程。这包括选择要编译进内核的模块和服务,以及调整相应的参数。 2. **配置方式**:Linux内核配置通常有三种方式:`make ...
steps-to-compile-linux-kernel.rar_linux
09-23
对于开发者和系统管理员来说,了解并能够编译Linux内核是一项重要的技能。本文将详细介绍如何编译Linux内核,适用于对Linux感兴趣的学习者。 **一、准备工作** 在开始编译前,确保你的系统已经安装了以下工具: 1...
linux-kernel.zip_kernel 定制
09-24
这个名为"linux-kernel.zip"的压缩包文件包含了针对Linux内核定制的详细指导,特别适合那些初学者,他们希望通过自定义内核来满足特定的需求或优化系统的性能。 Linux内核是操作系统的核心部分,它负责管理硬件资源...
Linux kernel启动过程
四季帆的博客
05-14 654
0. 声明 kernel版本号3.10.53 1. 链接脚本 arch/arm/kernel/vmlinux.lds.S ==>vmlinux.lds 生成的链接脚本(vmlinux.lds)中的重点内容如下: OUTPUT_ARCH(arm) ENTRY(stext) ······ 根据链接脚本可知kernel执行入口为stext,搜索stext即可得到入口函数的定义。 2. 入口函数(stext)实现 arch/arm/kernel/head.S stext
Linux 内核(Kernel启动流程
y_q_m的博客
03-30 232
[kernel 启动流程] (第二章)第一阶段之——设置SVC、关闭中断
ooonebook的博客
10-10 9057
本文是基于arm平台。例子都是以tiny210(s5pv210 armv7)为基础的。 参考文档《ARMV7官方数据手册 》零、说明本文是《[kernel 启动流程] (第一章)概述》的延伸, 阅读本文前建议先阅读《[kernel 启动流程] (第一章)概述》1、kernel启动流程第一阶段简单说明arch/arm/kernel/head.S kernel入口地址对应stext ENTRY(st
Linux kernel启动流程第一阶段
liangzaiEvil的博客
12-11 3740
kernel启动第一阶段: 工作需要对kernel部分的启动流程进行学习,其中均为查找网络资源所得。
Linux内核启动流程
qq_41781462的博客
05-04 4874
linux内核启动前, boot loader会将存储介质中的 initrd 文件加载到内存,内核启动时会在访问真正的根文件系统前先访问该内存中的 initrd 文件系统。在 bootloader 配置了 initrd 的情况下,内核启动被分成了两个阶段,第一阶段先执行 initrd 文件系统中的"某个文件",完成加载驱动模块等任务,第二阶段才会执行真正的根文件系统中的 /sbin/init 进程。98D板子,烧固件时用run upt,其实upt是一环境变量。u-boot启动内核的过程。
LinuxKernel启动流程分析
Michael_D_Sun的博客
03-14 484
文章目录1. 内核编译步骤2. 内核调用的层级关系 1. 内核编译步骤 一定一定要先读README!!! 1) make menuconfig, 对整个内核进行配置。 2) make uImage (header + kernel), 生成vmlinux.lds, 核心文件,找到kernel运行的起点。 head.S。 2. 内核调用的层级关系 以上就是内核启动过程的核心函数,以及调用层级关系, 详细内容还是需要自己去看代码了。 ...
Linux启动过程详解:从BIOS到Kernel Boot
本文主要探讨了Linux系统的启动过程,包括BIOS引导、GRUB加载、内核启动、Init...Linux启动过程的每一个步骤都至关重要,理解这些步骤有助于我们更好地管理和维护Linux系统,尤其是在解决启动问题时能提供宝贵的线索。
写文章

热门文章

  • ARM Cortex A7 架构简介 24614
  • ARM V8A体系结构-第十四章 多核处理器 4601
  • ARM V8A体系结构-第七章 AArch64的浮点和NEON 4166
  • linux-uboot 移植三 uboot启动内核过程 3766
  • ARM V8A体系结构-第六章 A64指令集 3674

最新评论

  • linux-uboot 移植一 uboot启动加载过程

    晴天晴天天天天: 芯片内部通常会内置一小段程序用于这个事情。搜索bootrom

  • linux-uboot 移植一 uboot启动加载过程

    HKTK-CWW: 请问linux是被uboot加载入内存的,但是在sd卡中的uboot是如何被加载入内存的呢(一开始没有初始化ddr)?

  • ARM V8A体系结构-第七章 AArch64的浮点和NEON

    晴天晴天天天天: ARMv8 官方精简版文档

  • ARM V8A体系结构-第七章 AArch64的浮点和NEON

    月满星沉: 博主你好,请问这是参考的哪个官方文档啊??

  • linux-uboot 移植四 uboot的移植

    shijugushanzh73543: 使用Setenv指令为什么会报错说没有这个指令啊,很奇怪

最新文章

  • vxWorks armV8a 多核启动过程
  • ARMv8函数传参中的bug!
  • linux-uboot 移植四 uboot的移植
2022年18篇
2021年9篇
2020年1篇
2019年11篇

目录

目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

玻璃钢生产厂家北京玻璃钢雕塑介绍深圳室内商场美陈销售企业福州多彩玻璃钢雕塑开业商场美陈多少钱兰州玻璃钢人像雕塑设计商场美陈展示流程密云商场开业美陈丰台区商场美陈价格徐汇区玻璃钢雕塑多少钱玻璃钢商业街人物雕塑广东节庆商场美陈供货商赣州景观玻璃钢雕塑宿州玻璃钢雕塑产品天津玻璃钢卡通雕塑松树湖南玻璃钢雕塑多少钱陕西景区玻璃钢雕塑哪家便宜晋宁玻璃钢仿生雕塑长沙商场美陈制作玻璃钢雕塑做油漆多少钱景区玻璃钢雕塑设计公司蓟县玻璃钢雕塑公司出售宁夏玻璃钢雕塑上海玻璃钢金属雕塑方案安康玻璃钢南瓜屋雕塑中山玻璃钢雕塑设计惠安玻璃钢花盆厂栖霞新年商场美陈山东动物玻璃钢雕塑多少钱甘肃玻璃钢基督教雕塑黑龙江佛像玻璃钢雕塑批发香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化