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

news/2025/2/16 5:27:15/

一.  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内核启动流程


http://www.ppmy.cn/news/1125459.html

相关文章

【数据结构-图】最短路径

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…

AI编程助手 Amazon CodeWhisperer 全面解析与实践

目录 引言Amazon CodeWhisperer简介智能编程助手智能代码建议代码自动补全 提升代码质量代码质量提升安全性检测 支持多平台多语言 用户体验和系统兼容性用户体验文档和学习资源个性化体验系统兼容性 功能全面性和代码质量功能全面性代码生成质量和代码安全性 CodeWhisperer的代…

[动物文学]走红年轻人化身“精神动物”,这届年轻人不想做人了

数据洞察流行趋势,敏锐把握流量风口。本期千瓜与您分享近期小红书八大热点内容,带您看热点、追热门、借热势,为您提供小红书营销布局风向标。 「动物文学」走红 年轻人化身“精神动物” 其实,这届年轻人“不想做人”很久了………

腾讯云微服务平台 TSF 异地多活单元化能力重磅升级

导语 2023腾讯全球数字生态大会已于9月7-8日完美落幕,40专场活动展示了腾讯最新的前沿技术、核心产品、解决方案。 微服务与消息队列专场,腾讯云微服务平台 TSF 产品经理张桢带来了《腾讯云微服务平台 TSF 异地多活单元化能力重磅升级》的精彩演讲。本…

ShapeableImageView 不只是圆形ImageView

偶然间看到了这位老哥的 https://juejin.cn/post/6869376452040196109#comment 文章&#xff0c;发现了ShapeableImageView–一个多形状的ImageView &#xff0c;虽然似乎发布了很久了&#xff0c;现在学习不晚。 效果图 布局文件 <com.google.android.material.imageview.S…

rust学习-string

介绍 A UTF-8–encoded, growable string(可增长字符串). 拥有string内容的所有权 A String is made up of three components: a pointer to some bytes, a length, and a capacity. The length is the number of bytes currently stored in the buffer pub fn as_bytes(&…

【Linux】C语言实现对文件的加密算法

异或加密 解密方式是进行第二次加密后自动解密 #define BUF_SIZE (16384) //16k /************************************************************** 功能描述: 加密实现 输入参数: --------------------------------------------------------------- 修改作者: 修改日期…

Java SE 21 新增特性

Java SE 21 新增特性 作者&#xff1a;Grey 原文地址&#xff1a; 博客园&#xff1a;Java SE 21 新增特性 CSDN&#xff1a;Java SE 21 新增特性 源码 源仓库: Github&#xff1a;java_new_features 镜像仓库: GitCode&#xff1a;java_new_features Record Patterns …