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 函数 */}
相关文章:
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安装包 打开网站,根据需求来下载;一般按照如下方式进行下载: 然后安装的时候记得按下图勾…...
树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...
多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...
网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...
华硕a豆14 Air香氛版,美学与科技的馨香融合
在快节奏的现代生活中,我们渴望一个能激发创想、愉悦感官的工作与生活伙伴,它不仅是冰冷的科技工具,更能触动我们内心深处的细腻情感。正是在这样的期许下,华硕a豆14 Air香氛版翩然而至,它以一种前所未有的方式&#x…...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
