当前位置: 首页 > 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安装包 打开网站,根据需求来下载;一般按照如下方式进行下载: 然后安装的时候记得按下图勾…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...

YSYX学习记录(八)

C语言&#xff0c;练习0&#xff1a; 先创建一个文件夹&#xff0c;我用的是物理机&#xff1a; 安装build-essential 练习1&#xff1a; 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件&#xff0c;随机修改或删除一部分&#xff0c;之后…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

【Go】3、Go语言进阶与依赖管理

前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课&#xff0c;做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程&#xff0c;它的核心机制是 Goroutine 协程、Channel 通道&#xff0c;并基于CSP&#xff08;Communicating Sequential Processes&#xff0…...

ServerTrust 并非唯一

NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...

反射获取方法和属性

Java反射获取方法 在Java中&#xff0c;反射&#xff08;Reflection&#xff09;是一种强大的机制&#xff0c;允许程序在运行时访问和操作类的内部属性和方法。通过反射&#xff0c;可以动态地创建对象、调用方法、改变属性值&#xff0c;这在很多Java框架中如Spring和Hiberna…...

拉力测试cuda pytorch 把 4070显卡拉满

import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试&#xff0c;通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小&#xff0c;增大可提高计算复杂度duration: 测试持续时间&#xff08;秒&…...

Angular微前端架构:Module Federation + ngx-build-plus (Webpack)

以下是一个完整的 Angular 微前端示例&#xff0c;其中使用的是 Module Federation 和 npx-build-plus 实现了主应用&#xff08;Shell&#xff09;与子应用&#xff08;Remote&#xff09;的集成。 &#x1f6e0;️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...

搭建DNS域名解析服务器(正向解析资源文件)

正向解析资源文件 1&#xff09;准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2&#xff09;服务端安装软件&#xff1a;bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...

C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...