Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >start_kernel函数部分分析

start_kernel函数部分分析

作者头像
哆哆jarvis
发布于 2022-08-23 06:14:05
发布于 2022-08-23 06:14:05
36100
代码可运行
举报
运行总次数:0
代码可运行

根据板子里面的启动信息,cat /proc/kmsg,对着代码看。

start_kernel函数分析

1. set_task_stack_end_magic(&init_task);

抽取关键部分

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  //找到栈顶位置并设置个魔术字,防止堆栈 将 thread_info 的数据覆盖;
  //如果是向上生长的栈,直接通过(task_thread_info + 8K - 1)找到栈底并设置魔术字
  //内核栈大小一般为4K或者8K.
  set_task_stack_end_magic(&init_task);
    stackend = end_of_stack(tsk);
      return (unsigned long *)(task_thread_info(p) + 1);
    *stackend = STACK_END_MAGIC; // 0x57AC6E9D
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//宏定义了就是向上生长
static inline unsigned long *end_of_stack(struct task_struct *p)
{
#ifdef CONFIG_STACK_GROWSUP
  return (unsigned long *)((unsigned long)task_thread_info(p) + THREAD_SIZE) - 1;
#else
  return (unsigned long *)(task_thread_info(p) + 1);
#endif
}

(栈向下生长的情况)

(栈向上生长的情况)

2. smp_setup_processor_id

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  int i;
  u32 mpidr = is_smp() ? read_cpuid_mpidr() & MPIDR_HWID_BITMASK : 0;
  u32 cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);

  cpu_logical_map(0) = cpu;
  for (i = 1; i < nr_cpu_ids; ++i)
    cpu_logical_map(i) = i == cpu ? 0 : i;

  /*
   * clear __my_cpu_offset on boot CPU to avoid hang caused by
   * using percpu variable early, for example, lockdep will
   * access percpu variable inside lock_release
   */
  set_my_cpu_offset(0);

  pr_info("Booting Linux on physical CPU 0x%x\n", mpidr);

先通过is_smp()函数判断是否为smp处理器

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
static inline bool is_smp(void)
{
#ifndef CONFIG_SMP
  return false;
#elif defined(CONFIG_SMP_ON_UP)
  extern unsigned int smp_on_up;
  return !!smp_on_up;
#else
  return true;
#endif
}

我的是imx6ull板子,不是对称多处理器,这里宏没定义,直接返回false。

所以mpidr 为0

3. local_irq_disable

暂时禁止本地中断, 设置完相关的东西后再开启

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  // 禁止本地中断
  local_irq_disable
    raw_local_irq_disable
      arch_local_irq_disable

4. boot_cpu_init

初始化 Boot CPU

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  // 设置boot cpu
  boot_cpu_init
    smp_processor_id
      raw_smp_processor_id
        current_thread_info()->cpu
    set_cpu_online
    set_cpu_active
    set_cpu_present
    set_cpu_possible

5.page_address_init

初始化高端内存线性地址中永久映射的全局变量.IMX6ULL这里的宏没开,所以这里应该是空

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  page_address_init
    // page_address_htable 是个全局结构体数组, 
    for (i = 0; i < ARRAY_SIZE(page_address_htable); i++)
      INIT_LIST_HEAD(&page_address_htable[i].lh);
      spin_lock_init(&page_address_htable[i].lock);

6.pr_notice("%s", linux_banner);

linux_banner 字符串保存了 linux 版本号,编译主机,GCC 版本,编译 时间等信息。在开机过程中可以看到log

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/* FIXED STRINGS! Don't touc.h! */
const char linux_banner[] =
  "Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
  LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";

以下是编译生成的文件,路径在include\generated\compile.h

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#define UTS_MACHINE "arm"
#define UTS_VERSION "#9 SMP PREEMPT Sat Dec 25 20:49:44 CST 2021"
#define LINUX_COMPILE_BY "zrc"
#define LINUX_COMPILE_HOST "zrc"
#define LINUX_COMPILER "gcc version 4.9.4 (Linaro GCC 4.9-2017.01) "

7. setup_arch

初始化体系相关的部分,实现与体系和芯片有关

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  // 初始化体系相关的部分,实现与体系和芯片有关
  setup_arch(&command_line)
    setup_processor(); // 从硬件获得体系相关的信息,并将该信息用于系统的初始化
    // __atags_pointer 指向 DTB 所在的物理地址
    mdesc = setup_machine_fdt(__atags_pointer)
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-12-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 哆哆jarvis 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
第3阶段——内核启动分析之start_kernel初始化函数(5)
诺谦
2018/01/03
1.8K0
手把手教你分析 Linux 启动流程
最新 Linux 内核是 5.15 版本。现在常用 Linux 内核源码为4.14、4.19、4.9 等版本,其中 4.14 版本源码压缩包大概 90+M,解压后 700+M,合计 61350 个文件。如此众多的文件,用 source insight 或者 VSCode 查看都会比较卡,所以可以采用在线查看的方式。
Jasonangel
2021/10/12
1K0
06.内核启动流程分析之内核启动
内核最终目的:运行根文件系统的应用程序 内核做的事情: 处理uboot传入的参数 arch\arm\kernel /*启动内核:bi_arch_number机器ID。参数存放的地址 bd->bi_boot_params*/ theKernel (0, bd->bi_arch_number, bd->bi_boot_params); 判断是否支持单板(根据启动内核时传入的机器ID) /**/ ENTRY(stext) msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MOD
嵌入式与Linux那些事
2021/05/20
9110
ARM64 SMP多核启动(下)- PSCI
上面说了pin-table的多核启动方式,看似很繁琐,实际上并不复杂,无外乎主处理器唤醒从处理器到指定地址上去执行指令,说他简单是相对于功能来说的,因为他只是实现了从处理器的启动,仅此而已,所以,现在社区几乎很少使用spin-table这种方式,取而代之的是psci,他不仅可以启动从处理器,还可以关闭,挂起等其他核操作,现在基本上arm64平台上使用多核启动方式都是psci。下面我们来揭开他神秘的面纱,其实理解了spin-table的启动方式,psci并不难(说白了也是需要主处理器给从处理器一个启动地址,然后从处理器从这个地址执行指令,实际上比这要复杂的多)。
用户7244416
2021/08/06
3K0
linux kernel的cmdline参数解析原理分析
Kernel启动时会解析cmdline,然后根据这些参数如console root来进行配置运行。
233333
2022/05/10
3.1K0
内核线程的创建和运行
通过 ps 命令可以看到红色方框标出的都是父进程为2号进程的内核线程,2号进程即蓝色方框标出的进程 kthreadd,1号进程是绿色方框标出的进程 init,它们的父进程号都是0。
刘盼
2021/07/05
1.8K2
内核线程的创建和运行
[kernel] 带着问题看源码 —— 进程 ID 是如何分配的
在《[apue] 进程控制那些事儿 》一文中,曾提到进程 ID 并不是唯一的,在整个系统运行期间一个进程 ID 可能会出现好多次。
海海
2024/05/16
1690
[kernel] 带着问题看源码 —— 进程 ID 是如何分配的
第三课:linux内核对设备树的处理
转载请注明文章地址 http://wiki.100ask.org/Linux_devicetree
韦东山
2020/09/30
1.6K0
第三课:linux内核对设备树的处理
《Linux内核分析》之分析fork函数对应的系统调用处理过程
xref: /linux-3.18.6/include/linux/sched.h
WindCoder
2018/09/20
1.1K0
《Linux内核分析》之分析fork函数对应的系统调用处理过程
Linux0号进程,1号进程,2号进程
本节我们将从linux启动的第一个进程说起,以及后面第一个进程是如何启动1号进程,然后启动2号进程。然后系统中所有的进程关系图做个简单的介绍
DragonKingZhu
2020/03/24
7.1K1
软中断SOFTIRQ
软中断的出现和linux系统对中断的划分是分不开的。linux系统将整个中断处理过程分为了两部分,分别为上半部(Top Half)和下半部(Bottom Half),之所以要这样分是因为关闭中断的时间不能过长,也就是在关闭中断期间尽可能少干事,否则影响整个系统的性能。所以linux系统将中断处理分为两部分,在上半部全程关闭中断,下半部打开中断。而在上半部主要干一些和硬件有关的操作,速度快,在下部分做一些耗时的操作。这样一来既能保证系统效率又能处理各种中断。
DragonKingZhu
2020/03/24
2.5K0
深入 kernel panic 流程【转】
我们在项目开发过程中,很多时候会出现由于某种原因经常会导致手机系统死机重启的情况(重启分Android重启跟kernel重启,而我们这里只讨论kernel重启也就是 kernel panic 的情况),死机重启基本算是影响最严重的系统问题了,有稳定复现的,也有概率出现的,解题难度也千差万别,出现问题后,通常我们会拿到类似这样的kernel log信息(下面log仅以调用BUG()为例,其它异常所致的死机log信息会有一些不同之处):
233333
2018/08/10
4.9K0
深入 kernel panic 流程【转】
高端内存映射之kmap_atomic固定映射--Linux内存管理(二十一)
linux高端内存中的临时内存区为固定内存区的一部分, 对于固定内存在linux内核中有下面描述
233333
2019/01/03
2.6K0
深入理解 kernel panic 的流程
我们在项目开发过程中,很多时候会出现由于某种原因经常会导致手机系统死机重启的情况(重启分Android重启跟kernel重启,而我们这里只讨论kernel重启也就是 kernel panic 的情况),死机重启基本算是影响最严重的系统问题了,有稳定复现的,也有概率出现的,解题难度也千差万别,出现问题后,通常我们会拿到类似这样的kernel log信息(下面log仅以调用BUG()为例,其它异常所致的死机log信息会有一些不同之处):
刘盼
2023/01/05
2.3K0
深入理解 kernel panic 的流程
第3阶段——内核启动分析之创建si工程和分析stext启动内核函数(4)
目标: (1)创建Source Insight 工程,方便后面分析如何启动内核的 (2)分析uboot传递参数,链接脚本如何进入stext的  (3) 分析stext函数如何启动内核:  (3.1
诺谦
2018/01/03
1K0
第3阶段——内核启动分析之创建si工程和分析stext启动内核函数(4)
Linux下0号进程的前世(init_task进程)今生(idle进程)----Linux进程的管理与调度(五)【转】
Linux下有3个特殊的进程,idle进程(PID = 0), init进程(PID = 1)和kthreadd(PID = 2)
233333
2018/09/14
5.3K0
Linux下0号进程的前世(init_task进程)今生(idle进程)----Linux进程的管理与调度(五)【转】
linux内核断点调试入门
上篇文章 编译一个默认输出hello world的linux内核 中,我们已经知道如何编译一个可以自运行的linux内核,这篇文章我们来看下如何对内核进行断点调试。
KINGYT
2020/04/13
3.6K0
Linux内核硬中断 / 软中断的原理和实现
从本质上来讲,中断是一种电信号,当设备有某种事件发生时,它就会产生中断,通过总线把电信号发送给中断控制器。
秃头哥编程
2019/10/09
23K1
Linux内核硬中断 / 软中断的原理和实现
吐血整理 | 肝翻 Linux 中断所有知识点
GIC,Generic Interrupt Controller。是ARM公司提供的一个通用的中断控制器。主要作用为:接受硬件中断信号,并经过一定处理后,分发给对应的CPU进行处理。
刘盼
2021/08/25
4.1K1
吐血整理 | 肝翻 Linux 中断所有知识点
Linux中断 - IDT
中断描述符表简单来说说是定义了发生中断/异常时,CPU按这张表中定义的行为来处理对应的中断/异常。
扫帚的影子
2020/02/18
6.9K0
Linux中断 - IDT
相关推荐
第3阶段——内核启动分析之start_kernel初始化函数(5)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验