ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

内核启动流程-初探

2022-02-10 23:03:00  阅读:349  来源: 互联网

标签:__ kernel head text 流程 lds init 内核 初探


目录

1. Question

  1. 内核启动入口在哪,怎么从代码中找到入口?
  2. 启动内核前,要有哪些准备工作?
  3. 进程调度是何时开始的?
  4. 多核启动是何时完成的?

2. 程序入口

基于linux-5.15 ARM64分析。

2.1. _text

从链接脚本arch/arm64/kernel/vmlinux.lds可以查到,程序的入口为_text,镜像起始位置存放的是.head.text段生成的指令码。搜索.head.text,可以找到include/linux/init.h__HEAD定义.section ".head.text","ax"

ENTRY(_text)

SECTIONS
{
 . = ((((((-(((1)) << ((((48))) - 1)))) + (0x08000000))) + (0x08000000)));
 .head.text : {
  _text = .;
  KEEP(*(.head.text))
 }
/* For assembly routines */
#define __HEAD      .section    ".head.text","ax"
#define __INIT      .section    ".init.text","ax"
#define __FINIT     .previous

再看一下arch/arm64/kernel/vmlinux.lds是怎么生成的,编译日志中,会有LDS arch/arm64/kernel/vmlinux.ldsscripts/Makefile.build中可以看到,也就是通过对arch/arm64/kernel/vmlinux.lds.S进行预处理得到了最终的链接脚本。

# Linker scripts preprocessor (.lds.S -> .lds)
# ---------------------------------------------------------------------------
quiet_cmd_cpp_lds_S = LDS     $@
      cmd_cpp_lds_S = $(CPP) $(cpp_flags) -P -U$(ARCH) \
                             -D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $<

$(obj)/%.lds: $(src)/%.lds.S FORCE
        $(call if_changed_dep,cpp_lds_S)

2.2. head.S

再搜索__HEAD,可以看到程序起始代码位于arch/arm64/kernel/head.S。通过代码梳理出内核启动基本流程。

__HEAD
/*
 * DO NOT MODIFY. Image header expected by Linux boot-loaders.
 */
efi_signature_nop           // special NOP to identity as PE/COFF executable
b   primary_entry           // branch to kernel start, magic
.quad   0                   // Image load offset from start of RAM, little-endian
le64sym _kernel_size_le         // Effective size of kernel image, little-endian
le64sym _kernel_flags_le        // Informative flags, little-endian
.quad   0               // reserved
.quad   0               // reserved
.quad   0               // reserved
.ascii  ARM64_IMAGE_MAGIC       // Magic number
.long   .Lpe_header_offset      // Offset to the PE header.

3. 内核启动基本流程

3.1. head.S

  1. 建立页表
  2. 开启MMU
  3. 跳转到start_kernel

3.2. start_kernel

start_kernel执行setup_arch和一些子系统的初始化,最后通过rest_init创建kernel_init和kthreadd两个线程,分别为1号和2号线程。kernel_init的工作主要通过kernel_init_freeable完成

  1. 执行early_initcall指定的函数
  2. 拉起从CPU,并启动多核调度
  3. 通过do_initcalls执行built-in到内核的各个initcall
  4. 挂载根文件系统
  5. 执行根文件系统中的init程序,kernel_init演变为init进程,内核也随之切换到用户态

标签:__,kernel,head,text,流程,lds,init,内核,初探
来源: https://www.cnblogs.com/owoxboyz/p/15881420.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有