3.2.6 盘古开天地start_kernel

news2024/9/23 15:22:47

点击查看系列文章 =》 Interrupt Pipeline系列文章大纲-CSDN博客

        3.2 内核初始化(盘古开天地)

                3.2.1 内核初始化的神话
                3.2.2 从头 (Head)开始
                3.2.3 从头初始化到身体
                3.2.4 宇之内存的空分复用
                3.2.5 宙之CPU的时分复用
                3.2.6 盘古开天地start_kernel

3.2.6 盘古开天地start_kernel

       __primary_switched最后义无反顾的跳转到了start_kernel(init/main.c)。为什么说义无反顾?因为使用的是b汇编指令而不是bl汇编指令,代表着跳转之后压根没有回头路。而且,前面已经构造好了栈空间,已经可以放心的执行C函数start_kernel。

       盘古开天辟地开始了,创世纪开始了,start_kernel实际上开始进行各种子系统的初始化。具体初始化过程有很多文章和书籍都有分析,就不一一赘述了。重点关注和中断相关的初始化。

第542行,关闭中断。实际上从内核运行开始一直都是关中断的,此处算是一个双保险操作。因为I-pipe要区分物理中断和虚拟中断,对此处会根据需要进行修改,后面会详细分析。

第590行,trap_init()定义在arch/arm64/kernel/traps.c,它的主要作用是:启用BRK指令为BUG()服务,在commit 9fb7410f955f7引入。__ipipe_init_early在trap_init()之前调用。

第637行,early_irq_init()定义在kernel/irq/irqdesc.c,初始化预分配的中断preallocated irqs。对于ARM64,dmesg启动过程中打印preallocated irqs为0,所以判断针对ARM64没有实质内容。

[    0.000000] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0

第638行,init_IRQ()真正进行ARM64中断初始化。

start_kernel <init/main.c>						
->	init_IRQ <arch/arm64/kernel/irq.c>					
	->	irqchip_init <drivers/irqchip/irqchip.c>				
		->	of_irq_init(__irqchip_of_table) <drivers/of/irq.c>			
			->	gic_of_init <drivers/irqchip/irq-gic-v3.c>		
				->	gic_init_bases <drivers/irqchip/irq-gic-v3.c>	
					->	set_handle_irq(gic_handle_irq)

第645行,time_init()对时钟进行初始化。__ipipe_init()的实质初始化,就放在了中断和时间子系统初始化之后。

第657行,打开中断。I-pipe会对local_irq_enable()进行改造,把它的语义从打开物理中断变成打开虚拟中断。

       盘古开天辟地的最后一步,就是分出天和地,start_kernel的最后一步是rest_init,也有异曲同工之妙。对代码进行精简,只保留最核心的部分:

static noinline void __ref rest_init(void)
{
    ……
	pid = kernel_thread(kernel_init, NULL, CLONE_FS);
    ……
	pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);
    ……
	cpu_startup_entry(CPUHP_ONLINE);
}
  • 辟地之创建1号进程init

        1号进程是0号进程调用kernel_thread->_do_fork创建的,本身是一个内核进程。1号进程的入口函数是kernel_init,它在当前根目录下寻找init程序,通过execve执行init程序转到用户态,变身为用户进程。

        此时的init程序实际上来自于initramfs或initrd,为方便描述,简称oldroot/init。它的职责是从initramfs或initrd中加载驱动并找到真正的根文件系统newroot,调用switch_root切换到newroot,并执行newroot/init程序。最重要的点是,newroot/init的进程号依然是1,这是怎么做到的?从switch_root源码可知,它复用了原来的1号进程,调用execv(init, initargs)重新装载newroot/init程序并执行,可以说是偷梁换柱的高手。当前,在嵌入式Linux中,经常把initramfs或initrd之间当作根文件系统,原理就是把oldroot/init的职责变更了,不再寻找newroot了,反而自己当家作主了,有点鸠占鹊巢的意思。

        Linux操作系统先后出现2个主流的init程序:System-V init和systemd。嵌入式Linux很多还在用System-V init,但是主流Linux发行版(例如红帽、Ubuntu)都在使用systemd.

        总而言之,1号进程init是所有用户进程的祖先!这里把它当作"地进程"!

        0 号进程在初始化阶段,无论是变量名还是函数名都使用了init前缀或后缀(例如init_task/init_stack等),而1号进程竟然也叫init进程,要特别注意不要混淆。

  • 开天之创建2号进程kthreadd

        2号进程是0号进程调用kernel_thread->_do_fork创建的,是一个内核进程,入口函数是kthreadd,它利用循环不断地判断kthread_create_list链表节点是否不为空,只要不为空,就取出链表节点,调用create_kthread-> kernel_thread->_do_fork创建相应的内核线程,然后删除链表节点。

        内核提供kthread_create/kthread_run来创建内核线程,实际上是向kthread_create_list链表添加新的链表节点,然后等待2号进程完成内核线程的创建。

        总而言之,2号进程kthreadd也是今后所有内核进程的祖先!这里把它当作”天进程“!

  • 0号进程swapper完成使命,变身闲云野鹤地”idle进程“

        当走到rest_init->cpu_startup_entry,意味着0号进程swapper已经完成了自己的使命,最终循环调用do_idle函数。只有当这个CPU上没有其它可运行的进程时,调度器才会选择执行进程0,让CPU进入空闲状态。0号进程因此有个绰号叫做idle进程。

 点击查看系列文章 =》 Interrupt Pipeline系列文章大纲-CSDN博客

原创不易,需要大家多多鼓励!您的关注、点赞、收藏就是我的创作动力!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2071396.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

abc 366 E+F(曼哈顿距离 x y 两个坐标分别计算)(贪心+01背包)

E题&#xff1a; 题意&#xff1a;给定的 xi yi 。求有多少点 到给人 若干定点 的曼哈顿距离 和 小于等于D. 因为D 最大时 1e6,-1e6<xi<1e6。 所以 可能的 点 的 x 的范围是 [-2e6 2e6] 同理 y 的 范围 一样。 将 x y 分开讨论。 我们可以枚举 某个x 的 个数&#xff0…

聚类:k-Means 和 k-Medoid

1. 前言 在《对静态分析缺陷报告进行聚类&#xff0c;以降低维护成本》 提到使用 k-Medoid 通过相似缺陷的聚类&#xff0c;来减少程序员对大量缺陷分析的工作量。 k-Medoid 和传统的 k-Means 聚类算法有什么差别呢&#xff1f; 简单的说&#xff0c;K-Medoid 算法是一种基于…

golang RSA 解密前端jsencrypt发送的数据时异常 crypto/rsa: decryption error 解决方法

golang中 RSA解密前端&#xff08;jsencrypt&#xff09;发来的密文后出现 "crypto/rsa: decryption error" &#xff0c; 这个问题首先需要确认你的私匙和公匙是否匹配&#xff0c; 如果匹配 那检查入参数据类型&#xff0c; 前端发送来的rsa加密后的数据一般都是…

《黑神话:悟空》到底是用什么语言开发的

《黑神话&#xff1a;悟空》&#xff08;Black Myth: Wukong&#xff09;是一款由中国游戏开发公司游戏科学&#xff08;Game Science&#xff09;开发的动作角色扮演游戏。该游戏主要使用了以下技术栈&#xff1a; 开发引擎&#xff1a;游戏科学公司使用了**虚幻引擎5&#x…

blender--二维平面图标变为三维网格

有时候我们希望把一些二维图片能变成三维网格&#xff0c;本案例我们就针对这一场景进行实现。 首先我们可以先去找一张需要的图片(注意&#xff0c;本例需要图片是svg格式)&#xff0c;我们可以在阿里巴巴矢量图标库等平台进行搜索&#xff0c;如图所示&#xff0c;找到需要的…

Python优化算法12——蝴蝶优化算法(BOA)

科研里面优化算法都用的多&#xff0c;尤其是各种动物园里面的智能仿生优化算法&#xff0c;但是目前都是MATLAB的代码多&#xff0c;python几乎没有什么包&#xff0c;这次把优化算法系列的代码都从底层手写开始。 需要看以前的优化算法文章可以参考&#xff1a;Python优化算…

ProtoBuf简要介绍与快速上手使用(C++版)

文章目录 一、 初识ProtoBuf1. 序列化和反序列化概念2. ProtoBuf是什么3. ProtoBuf的使用特点 二、 讲解说明三、 快速上手1. 创建 .proto 文件2. 编译 contacts.proto 文件&#xff0c;生成C文件3. 序列化与反序列化的使用4. 小结 ProtoBuf 使用流程 一、 初识ProtoBuf 1. 序…

线程是什么?和进程区别是什么?怎么用?

目录 一、什么是进程 二、什么是线程 总结&#xff1a;线程和进程的区别&#xff1f; 三、线程的使用 四、线程的调用 一、什么是进程 进程&#xff0c;也叫任务。就是正常执行的程序。 一个程序有两种状态&#xff1a; 一是没有被执行&#xff0c;在硬盘上躺着的软件&…

Qt Example Callout Extention(about QChart/QGraphicsView/QGraphicsItem)

问题 Qt Example callout 展示了在平面直角坐标系中画tips。知识点涉及到QChart/QGraphicsView/QGraphicsItem。如何在平面直角坐标系中画点、折线、圆、长方形&#xff1f; Example路径 D:\Qt\5.15.2\Src\qtcharts\examples\charts\callout\callout.cpp 代码 main #incl…

C++ 有向图拓扑排序算法

代码 #include <algorithm> #include <cassert> #include <functional> #include <map> #include <memory> #include <queue> #include <set> #include <unordered_set> #include <vector>namespace jc {template <…

【JAVA基础】位运算

文章目录 位运算按位与操作按位或操作按位取反按位亦或 移位运算有符号左移有符号右移 位运算 处理数据的时候可以直接对组成整形数值的各个位完成操作 &|~^andornotxor 下面我们以byte类型为例子&#xff1a; 按位与操作 两个操作数&#xff0c;如果同为1则为1&#…

【JavaEE初阶】IP协议

目录 &#x1f4d5;引言 &#x1f334;IP协议的概念 &#x1f333;IP数据报 &#x1f6a9;IPv4协议头格式 &#x1f6a9;IPv6的诞生 &#x1f3c0;拓展 &#x1f384;IP地址 &#x1f6a9;IP地址的格式&#xff1a; &#x1f6a9;IP地址的分类 &#x1f3c0;网段划分…

【计算机三级-数据库技术】操作题大题(第七套)

第七套操作题 第46题 假定要建立一个关于篮球职业联盟的数据库&#xff0c;需管理如下信息&#xff1a; 每个球队有球队名称、所在城市&#xff1b; 每位球员有球员姓名、薪酬; 每场比赛有比赛编号、比赛时间、比赛结果、参加比赛的主场球队、参加比赛的客场球队。 其中带下划…

Redis—基础篇

Redis基础 1. Redis 简介2. Redis 应用3. Redis 数据结构3.1 String3.2 hash3.3 list3.4 set3.5 sorted set 4. Redis 为什么快&#xff1f;5. Redis I/O 多路复用6. Redis 6.0多线程 1. Redis 简介 Redis 是一种基于键值对的 NoSQL 数据库 Redis 中的 value 支持 string、ha…

关于jupyter notebook 的输出 (outputs )

jupyter notebook 的输出 (outputs )在元素达到一定的个数后&#xff0c;就会按一行一个元素进行展示&#xff0c;百来个还好&#xff0c;一旦过千&#xff0c;那滚轮势必撸冒烟&#xff0c;所以能不能解决呢&#xff1f; 先看个例子&#xff0c; 一个找质数、合数的函数 cal3&…

【Linux篇】vim编译器

1. 介绍 vi / vim是visual interface的简称&#xff0c;是Linux中最典型的文本编辑器。 同图形化界面中的文本编辑器一样&#xff0c;vi是命令行下对文本文件进行编辑的绝佳选择。 vim是vi的加强版本&#xff0c;兼容vi的所有指令&#xff0c;不仅能编译文本&#xff0c;而且…

排序补充之快排的三路划分法

排序补充之快排的三路划分法 快排性能的关键点分析&#xff1a; 决定快排性能的关键点是每次单趟排序后&#xff0c;key对数组的分割&#xff0c;如果每次选key基本⼆分居中&#xff0c;那么快 排的递归树就是颗均匀的满⼆叉树&#xff0c;性能最佳。但是实践中虽然不可能每次…

数学建模笔记(四):熵权

背景&基本思想介绍 在实际的评价类问题中&#xff0c;在前面所说的层次分析法以及Topsis法中&#xff0c;指标权重的确定往往是通过主观的评价得来的&#xff0c;如果在没有专家的情况下&#xff0c;我们自己的权重分配往往可能带有一定的主观性&#xff0c;有没有一种可以…

linux系统离线安装docker并配置阿里云镜像源

制作docker.service文件 创建docker.service文件 cd /etc/systemd/system/ touch docker.service编辑docker.service文件 vim docker.service// 注意&#xff0c;将其中的ip地址&#xff0c;改成您的服务器地址&#xff0c;其它参数不用改。 //--insecure-registry192.168.8…

代码随想录算法day22 | 回溯算法part04 | 491.递增子序列,46.全排列,47.全排列 II

491.递增子序列 本题和大家做过的 90.子集II 非常像&#xff0c;但又很不一样&#xff0c;很容易掉坑里。 力扣题目链接(opens new window) 给定一个整型数组, 你的任务是找到所有该数组的递增子序列&#xff0c;递增子序列的长度至少是2。 示例: 输入: [4, 6, 7, 7]输出: [[4,…