当前位置: 首页 > news >正文

Linux内核启动流程-第二阶段start_kernel 函数

一.  Linux内核启动

上一篇文章简单介绍了 Linux内核启动的第一阶段,即执行汇编流程。

本文简单了解一下,Linux内核启动的第二阶段:start_kernel函数,这是一个 C 函数。

本文续上一篇文章的学习,地址如下:

Linux内核启动流程-第一阶段汇编流程简介_凌肖战的博客-CSDN博客

二.  Linux内核启动-start_kernel函数

start_kernel 通过调用众多的子函数来完成 Linux 启动之前的一些初始化工作,由于 start_kernel 函数里面调用的子函数太多,而这些子函数又很复杂,因此我们简单的来看一下一 些重要的子函数。

精简并添加注释后的 start_kernel 函数内容如下:

asmlinkage __visible void __init start_kernel ( void )
{
char * command_line ;
char * after_dashes ;
lockdep_init ();       /* lockdep 是死锁检测模块,此函数会初始化
                              * 两个 hash 表。此函数要求尽可能早的执行!
                              */
set_task_stack_end_magic (& init_task );  /* 设置任务栈结束魔术数,
                                                                  *用于栈溢出检测
                                                                  */
smp_setup_processor_id ();    /* SMP 有关 ( 多核处理器 ) ,设置处理器 ID
                                                * 有很多资料说 ARM 架构下此函数为空函数,那是因
                                                * 为他们用的老版本 Linux,而那时候 ARM 还没有多
                                                * 核处理器。
                                                */
debug_objects_early_init ();     /* 做一些和 debug 有关的初始化 */
boot_init_stack_canary ();        /* 栈溢出检测初始化 */
cgroup_init_early ();                 /* cgroup 初始化, cgroup 用于控制 Linux 系统资源 */
local_irq_disable ();                  /* 关闭当前 CPU 中断 */
early_boot_irqs_disabled = true ;
/*
* 中断关闭期间,做一些重要的操作,然后打开中断
*/
boot_cpu_init ();                          /* 跟 CPU 有关的初始化 */
page_address_init ();                  /* 页地址相关的初始化 */
pr_notice ( "%s" , linux_banner );   /* 打印 Linux 版本号、编译时间等信息 */
setup_arch (& command_line );    /* 架构相关的初始化,此函数会解析传递进来的
                                                    * ATAGS 或者设备树(DTB)文件。会根据设备树里面
                                                    * 的 model 和 compatible 这两个属性值来查找
                                                    * Linux 是否支持这个单板。此函数也会获取设备树
                                                    * 中 chosen 节点下的 bootargs 属性值来得到命令
                                                    * 行参数,也就是 uboot 中的 bootargs 环境变量的
                                                    * 值,获取到的命令行参数会保存到
                                                    *command_line 中。
                                                     */
mm_init_cpumask (& init_mm );                 /* 看名字,应该是和内存有关的初始化 */
setup_command_line ( command_line );    /* 好像是存储命令行参数 */
setup_nr_cpu_ids ();                          /* 如果只是 SMP( 多核 CPU) 的话,此函数用于获取
                                                           * CPU 核心数量,CPU 数量保存在变量
                                                           * nr_cpu_ids 中。
                                                           */
setup_per_cpu_areas ();         /* SMP 系统中有用,设置每个 CPU per-cpu 数据 */
smp_prepare_boot_cpu ();
build_all_zonelists ( NULL , NULL );     /* 建立系统内存页区 (zone) 链表 */
page_alloc_init ();                                /* 处理用于热插拔 CPU 的页 */
pr_notice ( "Kernel command line: %s\n" , boot_command_line );    /* 打印命令行信息 */
parse_early_param ();                                   /* 解析命令行中的 console 参数 */
after_dashes = parse_args ( "Booting kernel" ,
static_command_line , __start___param ,
__stop___param - __start___param ,
- 1 , - 1 , & unknown_bootoption );
if (! IS_ERR_OR_NULL ( after_dashes ))
parse_args ( "Setting init args" , after_dashes , NULL , 0 , - 1 , - 1 ,
set_init_arg );
jump_label_init ();
setup_log_buf ( 0 );   /* 设置 log 使用的缓冲区 */
pidhash_init ();       /* 构建 PID 哈希表, Linux 中每个进程都有一个 ID,
                               * 这个 ID 叫做 PID 。通过构建哈希表可以快速搜索进程
                               * 信息结构体。
                               */
vfs_caches_init_early ();    /* 预先初始化 vfs(虚拟文件系统) 的目录项和
                                           * 索引节点缓存
                                           */
sort_main_extable ();    /* 定义内核异常列表 */
trap_init ();                     /* 完成对系统保留中断向量的初始化 */
mm_init ();                     /* 内存管理初始化 */
 
sched_init ();                         /* 初始化调度器,主要是初始化一些结构体 */
preempt_disable ();               /* 关闭优先级抢占 */
if ( WARN (! irqs_disabled (),   /* 检查中断是否关闭,如果没有的话就关闭中断 */
"Interrupts were enabled *very* early, fixing it\n" ))
local_irq_disable ();
idr_init_cache ();             /* IDR 初始化, IDR Linux 内核的整数管理机
                                        * 制,也就是将一个整数 ID 与一个指针关联起来。
                                        */
rcu_init ();                   /* 初始化 RCU, RCU 全称为 Read Copy Update( - 拷贝修改 ) */
trace_init ();                /* 跟踪调试相关初始化 */
context_tracking_init ();
radix_tree_init ();
                                  /* 基数树相关数据结构初始化 */
early_irq_init ();         /* 初始中断相关初始化 , 主要是注册 irq_desc 结构体变
                                 * 量,因为 Linux 内核使用 irq_desc 来描述一个中断。
                                 */
init_IRQ ();                /* 中断初始化 */
tick_init ();                  /* tick 初始化 */
rcu_init_nohz ();
init_timers ();             /* 初始化定时器 */
hrtimers_init ();          /* 初始化高精度定时器 */
softirq_init ();              /* 软中断初始化 */
timekeeping_init ();
time_init ();                 /* 初始化系统时间 */
sched_clock_postinit ();
perf_event_init ();
profile_init ();
call_function_init ();
WARN (! irqs_disabled (), "Interrupts were enabled early\n" );
early_boot_irqs_disabled = false ;
local_irq_enable ();                 /* 使能中断 */
kmem_cache_init_late ();          /* slab 初始化, slab Linux 内存分配器 */
console_init ();                         /* 初始化控制台,之前 printk 打印的信息都存放
                                                * 缓冲区中,并没有打印出来。只有调用此函数
                                                * 初始化控制台以后才能在控制台上打印信息。
                                                */
if ( panic_later )
panic ( "Too many boot %s vars at `%s'" , panic_later ,
panic_param );
lockdep_info ();         /* 如果定义了宏 CONFIG_LOCKDEP ,那么此函数打印一些信息。 */
locking_selftest ()    /* 锁自测 */
......
page_ext_init ();
debug_objects_mem_init ();
kmemleak_init ();         /* kmemleak 初始化, kmemleak 用于检查内存泄漏 */
setup_per_cpu_pageset ();
numa_policy_init ();
if ( late_time_init )
late_time_init ();
sched_clock_init ();
calibrate_delay ();         /* 测定 BogoMIPS 值,可以通过 BogoMIPS 来判断 CPU 的性能
                                      * BogoMIPS 设置越大,说明 CPU 性能越好。
                                       */
pidmap_init ();    /* PID 位图初始化 */
anon_vma_init ();         /* 生成 anon_vma slab 缓存 */
acpi_early_init ();
......
thread_info_cache_init ();
cred_init ();                         /* 为对象的每个用于赋予资格( 凭证 ) */
fork_init ();                          /* 初始化一些结构体以使用 fork 函数 */
proc_caches_init ();         /* 给各种资源管理结构分配缓存
*/
buffer_init ();              /* 初始化缓冲缓存 */
key_init ();                 /* 初始化密钥 */
security_init ();         /* 安全相关初始化 */
dbg_late_init ();
vfs_caches_init ( totalram_pages );  /* VFS 创建缓存 */
signals_init ();                                 /* 初始化信号 */
page_writeback_init ();                      /* 页回写初始化 */
proc_root_init ();                         /* 注册并挂载 proc 文件系统 */
nsfs_init ();
cpuset_init ();          /* 初始化 cpuset cpuset 是将 CPU 和内存资源以逻辑性
                               * 和层次性集成的一种机制,是 cgroup 使用的子系统之一
                               */
cgroup_init ();                      /* 初始化 cgroup */
taskstats_init_early ();        /* 进程状态初始化 */
delayacct_init ();
check_bugs ();                    /* 检查写缓冲一致性 */
acpi_subsystem_init ();
sfi_init_late ();
if ( efi_enabled ( EFI_RUNTIME_SERVICES )) {
efi_late_init ();
efi_free_boot_services ();
}
ftrace_init ();
rest_init (); /* rest_init 函数 */
}

start_kernel 里面调用了大量的函数,每一个函数都是一个庞大的知识点,如果想要学习 Linux 内核,那么这些函数就需要去详细的研究。本文简单介绍一下 Linux内核启动流程

相关文章:

Linux内核启动流程-第二阶段start_kernel 函数

一. Linux内核启动 上一篇文章简单介绍了 Linux内核启动的第一阶段,即执行汇编流程。 本文简单了解一下,Linux内核启动的第二阶段:start_kernel函数,这是一个 C 函数。 本文续上一篇文章的学习,地址如下:…...

Disruptor:无锁队列设计的背后原理

简介 在高并发场景下,队列的速度和效率是关键。而Disruptor,一种高性能的并发队列,通过独特的设计,解决了传统队列在处理高并发时可能遇到的性能瓶颈。本文将深入分析Disruptor如何通过环形数组结构、元素位置定位以及无锁设计&a…...

网络编程-UDP协议(发送数据和接收数据)

需要了解TCP协议的,可以看往期文章 https://blog.csdn.net/weixin_43860634/article/details/133274701 TCP/IP参考模型 通过此图,可以了解UDP所在哪一层级中 代码案例 发送数据 package com.hidata.devops.paas.udp;import java.io.IOException; …...

AI绘画普及课【一】绘画入门

文章目录 一、AI 绘画入门1、Stable Diffusion VS. MidJourney2、Stable Diffusion 介绍3、Stable Diffusion 环境搭建4、文生图与图生图 一、AI 绘画入门 1、Stable Diffusion VS. MidJourney Midjourney 优点: 操作简单、出图绚丽多彩 缺点: 订阅付费充钱 内容有限制&a…...

Selenium和Requests搭配使用

Selenium和Requests搭配使用 前要1. CDP2. 通过requests控制浏览器2. 1 代码一2. 2 代码2 3. 通过selenium获取cookie, requests携带cookie请求 前要 之前有提过, 用selenium控制本地浏览器, 提高拟人化,但是效率比较低,今天说一种selenium和requests搭配使用的方法 注意: 一定…...

【JDK 8-函数式编程】4.4 Supplier

一、Supplier 接口 二、实战 Stage 1: 创建 Student 类 Stage 2: 创建方法 Stage 3: 调用方法 Stage 4: 执行结果 一、Supplier 接口 供给型 接口: 无入参,有返回值(T : 出参类型) 调用方法: T get(); 用途: 如 无参的工厂方法&#x…...

后端大厂面试-16道面试题

1 java集合类有哪些? List是有序的Collection,使用此接口能够精确的控制每个元素的插入位置,用户能根据索引访问List中元素。常用的实现List的类有LinkedList,ArrayList,Vector,Stack。 ArrayList是容量…...

产品经理认证(UCPM)备考心得

UCPM是联合国训练所CIFAL中心颁发的产品经理证书。如今,ESG是推动企业可持续发展的新潮流。UCPM作为一种可持续发展证书,为我们带来了一套先进科学、系统全面的产品管理模式,是产品管理领域公认的权威证书。那么,如何准备这张证书…...

E : A DS顺序表_删除有序表中的重复元素

Description 给定一个按升序排列的顺序表,请删除所有重复的元素,使得每个元素只出现一次,并输出处理后的顺序表。 Input 第一行输入t,表示有t个测试样例。 第二行起,每一行首先输入n,表示有n个元素&…...

前端教程-vite

官网 Vite中文网 视频教程 Vite世界指南(带你从0到1深入学习 vite)...

Java笔记三

包机制: 为了更好地组织类,Java提供了包机制,用于区别类名的命名空间。 包语句的语法格式为:pack pkg1[. pkg2[. pkg3...]]; 般利用公司域名倒置作为包名;如com.baidu.com,如图 导包: 为了能够…...

ElementUI之首页导航与左侧菜单

目录 一、Mock 1.1 什么是Mock.js 1.2 安装与配置 1.2.1 安装mock.js 1.2.2 引入mock.js 1.3 mock.js使用 1.3.1 定义测试数据文件 1.3.2 mock拦截Ajax请求 1.3.3 界面代码优化 二、总线 2.1 定义 2.2 类型分类 2.3 前期准备 2.4 配置组件与路由关系 2.4.1 配置…...

java项目之在线教育资源管理系统(ssm源码+文档)

项目简介 在线教育资源管理系统实现了以下功能: 管理员:个人中心、学生管理、教师管理、公告信息管理、课程信息管理、试题管理、留言板管理、管理员管理、试卷管理、系统管理、考试管理。学生:个人中心、留言板管理、考试管理,…...

C/S架构学习之UDP服务器

UDP服务器的实现流程:一、创建用户数据报套接字(socket函数):通信域选择IPV4网络协议、套接字类型选择数据报式; int sockfd socket(AF_INET,SOCK_DGRAM,0); 二、填充服务器的网络信息结构体:1.定义网络信…...

磁盘占用率100% 的优化方案

1.禁用不必要的系统服务 右键点击此电脑,打开管理 打开服务 寻找SysMain 右键属性 》 禁用 》 停止 》 应用 SysMain的作用:当开机后,windows会加载大量的应用程序预加载到内存中,会在后台预加载数据(如果是旧版本win…...

vue组件的通信

文章目录 组件通信父传子父传子:通过prop来进行通信 子传父先在父组件用注册方法 , 在子组件触发使用 emit 函数 组件间通信-平行组件使用事件总线的方法,也就是把整个vue提出来,当为一个事件总线 其他组件通信父组件 provide来提供变量,然后再子组件中通过inject来注入变量 组…...

(搞定)排序数据结构(1)插入排序 选择排序+冒泡排序

目录 本章内容如下 一:插入排序 1.1插入排序 1.2希尔排序 二:选择排序 2.1选择排序 三:交换排序 3.1冒泡排序 一:插入排序 1.1直接插入排序 说到排序,其实在我们生活中非常常见&…...

C++ 类访问修饰符 public、private、protected

数据封装是面向对象编程的一个重要特点,它防止函数直接访问类类型的内部成员。类成员的访问限制是通过在类主体内部对各个区域标记 public、private、protected 来指定的。关键字 public、private、protected 称为访问修饰符。 一个类可以有多个 public、protected…...

pytorch学习笔记——BCE与CE

BCELoss的话只需要网络输出一个通道,CE Loss(Cross Entropy Loss)需要输出n_class个通道。 对于二分类任务可以使用CE Loss输出两个通道,也可以使用BCE Loss输出一个通道。 https://www.jianshu.com/p/5b01705368bb https://zhuanlan.zhihu.com/p/372628…...

win使用git(保姆级教程)

序言 上学期间用的git并不多,但是从研三实习以及后面工作来看,git是一项必备技能,所以在此来学习一下。 下载git安装包 打开网站,根据需求来下载;一般按照如下方式进行下载: 然后安装的时候记得按下图勾…...

【网络】每天掌握一个Linux命令 - iftop

在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

51c自动驾驶~合集58

我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...

SciencePlots——绘制论文中的图片

文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了:一行…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​,覆盖应用全生命周期测试需求,主要提供五大核心能力: ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止

<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet&#xff1a; https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud&#xff0c;主要用于支持数据的抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;和加载&#xff08;Load&#xff09;过程。提供了一个简洁直观的界面&#xff0c;以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

相机从app启动流程

一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

04-初识css

一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包&#xff1a; for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

GruntJS-前端自动化任务运行器从入门到实战

Grunt 完全指南&#xff1a;从入门到实战 一、Grunt 是什么&#xff1f; Grunt是一个基于 Node.js 的前端自动化任务运行器&#xff0c;主要用于自动化执行项目开发中重复性高的任务&#xff0c;例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...