金乡县住房和城乡建设局网站,网站 改版 建议,住房和城乡建设部官网查证,漳州网站建设到博大一. Linux内核启动 上一篇文章简单介绍了 Linux内核启动的第一阶段#xff0c;即执行汇编流程。
本文简单了解一下#xff0c;Linux内核启动的第二阶段#xff1a;start_kernel函数#xff0c;这是一个 C 函数。 本文续上一篇文章的学习#xff0c;地址如下#xff1a;…一. 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内核启动流程。