简述start_kernel每个函数的作用

每个函数具体干了什么,还是得进去看代码,以下虽然只是很大概的一个总结,都花了十几个小时,所以,想真的弄明白一件事,就真得不怕花时间去做

asmlinkage __visible void __init start_kernel(void)
{
	char *command_line;
	char *after_dashes;

	/*
	 * Need to run as early as possible, to initialize the
	 * lockdep hash:
	 */
	lockdep_init(); //初始化锁依赖检测机制,用于检测和调试多线程并发程序中潜在的死锁和锁竞争问题
	set_task_stack_end_magic(&init_task); //设置魔数的目的是为了进行栈溢出检测,init_task是一个task_struct实例,后续创建0号idle进程会用到
	smp_setup_processor_id(); //获取当前正在执行初始化的处理器ID
	debug_objects_early_init(); //对调试对象进行早期的初始化,其实就是HASH锁和静态对象池进行初始化

	/*
	 * Set up the the initial canary ASAP:
	 */
	boot_init_stack_canary(); //用于检测缓冲区溢出漏洞攻击,它通过在栈上插入一个随机值来保护函数返回地址的完整性,函数返回时会检测这个随机值有没被篡改

	cgroup_init_early(); //初始化控制组,控制组是一种机制,用于对进程和资源进行分组和管理,以实现资源隔离、控制和限制。

	local_irq_disable(); //禁用本地硬件中断
	early_boot_irqs_disabled = true;

/*
 * Interrupts are still disabled. Do necessary setups, then
 * enable them
 */
	boot_cpu_init(); //初始化并激活当前cpu
	page_address_init(); //初始化高端内存
	pr_notice("%s", linux_banner);
	setup_arch(&command_line); //负责初始化与特定体系结构相关的硬件和特性,为内核提供正确的运行环境,里面初始化了memblock来管理内存
	mm_init_cpumask(&init_mm); //创建和初始化一个位图,记录可用的 CPU 的状态
	setup_command_line(command_line); //将启动参数存储在特定的结构里,方便后续访问
	setup_nr_cpu_ids(); //确定系统中可用 CPU 的数量,并设置相应的值
	setup_per_cpu_areas(); //为每个 CPU 单独分配的内存区域,用于存放每个 CPU 特定的变量和数据结构
	smp_prepare_boot_cpu();	/* arch-specific boot-cpu hooks */

	build_all_zonelists(NULL, NULL); //构建和初始化所有的zone列表,为每个CPU构建合适的zone列表,以便在分配内存时能够快速地找到合适的内存区域
	page_alloc_init(); //对页分配器进行初始化

	pr_notice("Kernel command line: %s\n", boot_command_line);
	parse_early_param(); //这个用的是bootloader传递过来的boot_command_line,通过这样来解析__setup( "foo="  , foo );
	after_dashes = parse_args("Booting kernel", //这个是编译时定义的静态command
				  static_command_line, __start___param,
				  __stop___param - __start___param,
				  -1, -1, NULL, &unknown_bootoption);
	if (!IS_ERR_OR_NULL(after_dashes))
		parse_args("Setting init args", after_dashes, NULL, 0, -1, -1,
			   NULL, set_init_arg);

	jump_label_init(); //初始化跳转标签,这是一种编译时优化机制,不像goto等需要运行时控制

	/*
	 * These use large bootmem allocations and must precede
	 * kmem_cache_init()
	 */
	setup_log_buf(0); //初始化日志缓冲区
	pidhash_init(); //初始化进程pid的hash表
	vfs_caches_init_early(); //早期初始化虚拟文件系统的缓存,在运行时更快地访问文件和目录
	sort_main_extable(); //链接时lds会确定异常表(页面错误,除0错误等)的开始和结束地址,中断向量表的地址在链接的时候也会确定,并在__enable_mmu赋值给vbar_el1寄存器
	trap_init(); //注册bug_break_hook处理trap
	mm_init(); //初始化内存管理,后续就由伙伴系统来管理页分配了

	/*
	 * Set up the scheduler prior starting any interrupts (such as the
	 * timer interrupt). Full topology setup happens at smp_init()
	 * time - but meanwhile we still have a functioning scheduler.
	 */
	sched_init(); //初始化调度器,0号idle进程通过fork就此诞生
	/*
	 * Disable preemption - early bootup scheduling is extremely
	 * fragile until we cpu_idle() for the first time.
	 */
	preempt_disable();
	if (WARN(!irqs_disabled(),
		 "Interrupts were enabled *very* early, fixing it\n"))
		local_irq_disable();
	idr_init_cache(); //初始化 IDR(ID Allocator)缓存
	rcu_init(); //初始化 RCU(Read-Copy-Update)子系统

	/* trace_printk() and trace points may be used after this */
	trace_init(); //traceponints初始化

	context_tracking_init(); //初始化上下文跟踪子系统,用于跟踪和记录任务之间的上下文切换信息
	radix_tree_init(); //初始化基数树,用于在内核中存储和检索key-value对
	/* init some links before init_ISA_irqs() */
	early_irq_init(); //通用逻辑,为irq_desc[]中各元素的某些成员填充默认值
	init_IRQ(); //初始化中断控制器,将硬件中断号跟irq对应,irq再跟中断处理函数通过irq_desc关联
	tick_init(); //设置定时器硬件以及与之相关的数据结构,以便在每个时钟中断时触发特定的操作
	rcu_init_nohz(); //用于初始化无硬中断负载下的可读复制更新
	init_timers(); //系统启动时负责初始化定时器机制,为操作系统提供时间轮询和在内核中使用定时器所需的基础设置
	hrtimers_init(); //初始化高分辨率定时器
	softirq_init(); //于在内核中通过软件方式处理延迟的任务和中断请求
	timekeeping_init(); //确保系统能够准确追踪时间,并提供一致和可靠的时间接口
	time_init(); //初始化系统的时钟源,并校准系统时间。
	sched_clock_postinit(); //准备好调度时钟,以便在后续的任务调度和时间相关操作中使用
	perf_event_init(); //它利用处理器的硬件性能计数器来收集各种硬件事件的计数信息,如指令执行、缓存命中、分支预测等等
	profile_init(); //用于初始化系统性能分析工具。通过该函数,可以注册事件处理函数、分配数据结构并执行其他初始化操作,以准备好性能数据的采集和分析
	call_function_init(); //初始化在多个CPU核心之间进行函数调用的机制
	WARN(!irqs_disabled(), "Interrupts were enabled early\n");
	early_boot_irqs_disabled = false;
	local_irq_enable(); //开启本地硬件中断

	kmem_cache_init_late(); //初始化内核中的内存缓存对象。这些内存缓存对象预先分配内存块,用于提高内核操作的效率并减少动态内存分配的开销

	/*
	 * HACK ALERT! This is early. We're enabling the console before
	 * we've done PCI setups etc, and console_init() must be aware of
	 * this. But we do want output early, in case something goes wrong.
	 */
	console_init(); //用于初始化控制台设备和驱动程序。它负责设置默认的控制台,注册驱动程序,并提供系统的初始控制台参数
	if (panic_later)
		panic("Too many boot %s vars at `%s'", panic_later,
		      panic_param);

	lockdep_info(); //打印锁的依赖信息

	/*
	 * Need to run this when irqs are enabled, because it wants
	 * to self-test [hard/soft]-irqs on/off lock inversion bugs
	 * too:
	 */
	locking_selftest(); //用于自检和测试锁机制的正确性和有效性

#ifdef CONFIG_BLK_DEV_INITRD //用于检测并处理 initrd 被覆盖的情况
	if (initrd_start && !initrd_below_start_ok &&
	    page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {
		pr_crit("initrd overwritten (0x%08lx < 0x%08lx) - disabling it.\n",
		    page_to_pfn(virt_to_page((void *)initrd_start)),
		    min_low_pfn);
		initrd_start = 0;
	}
#endif
	page_ext_init(); //初始化与页面相关的扩展数据结构
	debug_objects_mem_init(); //初始化调试对象内存分配器
	kmemleak_init(); //初始化内核内存泄漏检测器
	setup_per_cpu_pageset(); //遍历系统中所有的zone,对于每一个zone为所有的CPU分配pageset(冷热页缓存)并进行初始化
	numa_policy_init(); //初始化 NUMA 策略,它会设置所需的数据结构和状态,并进行一些初始化操作
	if (late_time_init)
		late_time_init();
	sched_clock_init(); //准备好调度时钟所需的资源,以便在后续的运行过程中能够准确地测量时间和进行任务调度
	calibrate_delay(); //校准计算loops_per_jiffies值,用于mdelay和ndelay
	pidmap_init(); //初始化进程标识符映射,为内核分配和设置必要的数据结构,以准备好处理进程标识符的分配和管理
	anon_vma_init(); //初始化匿名虚拟内存区
	acpi_early_init(); //初始化acpi,并填充acpi命名空间
#ifdef CONFIG_X86
	if (efi_enabled(EFI_RUNTIME_SERVICES))
		efi_enter_virtual_mode();
#endif
#ifdef CONFIG_X86_ESPFIX64
	/* Should be run before the first non-init thread is created */
	init_espfix_bsp();
#endif
	thread_info_cache_init(); //使用线程信息缓存来提前分配和管理这些线程信息的存储空间,以避免频繁的内存分配和释放操作
	cred_init(); //初始化进程凭据,凭据是与每个进程相关联的结构,用于表示进程的权限和身份信息
	fork_init(); //创建task_struct的一个slab,后续通过struct task_struct *task = kmem_cache_alloc(task_struct_cachep, GFP_KERNEL);
	proc_caches_init(); //创建和初始化这些与 /proc 文件系统相关的缓存。具体的初始化操作包括分配内存、初始化缓存数据结构等
	buffer_init(); //初始化一个buffer_head的slab缓存,供后续使用
	key_init(); //初始化密钥管理状态
	security_init(); //初始化安全子系统,包括注册安全模块、创建安全上下文等。
	dbg_late_init(); //初始化kdb_printf、断点表和kdb状态
	vfs_caches_init(); //始化 VFS 的缓存,包括 inode 缓存、dentry 缓存和文件缓存。这些缓存用于提高文件系统的性能和效率
	signals_init(); //初始化一个sigqueue的缓存
	/* rootfs populating might need page-writeback */
	page_writeback_init(); //初始化页面回写机制,包括创建回写线程、设置相关参数和数据结构等
	proc_root_init(); //用于创建 Proc 文件系统的根节点。它会为根节点分配内存并初始化相关的数据结构
	nsfs_init(); //初始化命名空间文件系统。它会创建命名空间文件系统的根目录,并注册相应的文件操作函数。通过访问命名空间文件系统,可以查看和设置命名空间的相关信息
	cpuset_init(); //初始化cpuset控制器,对进程或任务进行CPU和内存资源的管理、限制和隔离
	cgroup_init(); //用于初始化cgroup子系统,它通过将一组进程或任务进行组织和管理,提供了对系统资源的控制和限制,它会创建cgroupfs文件系统的根目录,注册相应的文件操作函数
	taskstats_init_early(); //它提供了对进程和任务的统计信息的收集和查询,以获取进程的CPU使用情况、内存使用情况、执行状态、生命周期等信息,以及与进程相关的网络统计信息
	delayacct_init(); //用于跟踪和统计进程或任务在延迟等待上所花费的时间,它可以统计进程等待磁盘 I/O、网络操作、锁等资源的时间,以及进程在等待中花费的总时间

	check_bugs(); //各个平台自己会选择是否填充这个

	acpi_subsystem_init(); //初始化 ACPI 子系统。它会完成与 ACPI 相关的数据结构和功能的初始化工作
	sfi_init_late(); //初始化SFI子系统,它完成与 SFI 相关的数据结构的初始化,并注册 SFI 的回调函数,以便从SFI固件中获取硬件配置信

	if (efi_enabled(EFI_RUNTIME_SERVICES)) {
		efi_late_init();
		efi_free_boot_services();
	}

	ftrace_init(); //初始化Ftrac子系统,处理mcount段的函数,mcount是一种静态插桩技术,在代码编译阶段进行处理。它通过在每个函数的开头添加记录函数调用信息的代码

	/* Do the rest non-__init'ed, we're now alive */
	rest_init(); //1号进程kernel_init驱动初始化完,就直接启动用户空间的init进程;2号进程kthreadd就用来创建内核进程了,0号idle进入cpu_startup_entry以在空闲时loop
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`enable_shared_from_this` 是 C++ 标准库提供的一个模板类,用于解决在某个类中获取自身的 `shared_ptr` 的问题。它的作用是允许一个对象在拥有 `shared_ptr` 的情况下,安全地获取到指向自身的 `shared_ptr`。 当一个类继承自 `enable_shared_from_this` 时,它就可以调用 `shared_from_this()` 成员函数来获取指向自身的 `shared_ptr`。这样可以确保在多个 `shared_ptr` 共享同一个对象时,不会因为对象被删除而导致悬空指针问题。 使用 `enable_shared_from_this` 的步骤如下: 1. 继承自 `enable_shared_from_this<T>`,其中 `T` 是派生类的类型。 2. 在需要获取自身的地方,调用 `shared_from_this()` 成员函数。 以下是一个示例代码: ```cpp #include <iostream> #include <memory> class MyClass : public std::enable_shared_from_this<MyClass> { public: std::shared_ptr<MyClass> getShared() { return shared_from_this(); } }; int main() { std::shared_ptr<MyClass> obj1 = std::make_shared<MyClass>(); std::shared_ptr<MyClass> obj2 = obj1->getShared(); std::cout << "obj1 use count: " << obj1.use_count() << std::endl; std::cout << "obj2 use count: " << obj2.use_count() << std::endl; return 0; } ``` 在这个示例中,`MyClass` 继承自 `enable_shared_from_this<MyClass>`,在 `getShared()` 函数中调用了 `shared_from_this()` 返回了一个指向自身的 `shared_ptr`。通过使用 `shared_ptr` 来管理对象的生命周期,可以确保在 `obj2` 存在时,`obj1` 不会被释放,从而避免了悬空指针问题。 需要注意的是,`enable_shared_from_this` 要求对象必须通过 `shared_ptr` 进行管理,否则会导致未定义行为。同时,不要在析构函数中使用 `shared_from_this()`,以避免潜在的问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值