【Linux内核|进程管理】0号线程swapper简介
12 人赞同了该文章 目录 收起 0. 说明 1. 总览 2. 汇编阶段的初始化 3. init_task结构体 4. bootcpu 0号线程的工作 4.1. start_kernel 4.2. 其他cpu的0号线程创建 4.3. 创建1号和2号线程 4.4. schedule_preempt_disabled 4.5. cpu_startup_entry 4.6. do_idle0. 说明
文章目录汇总:文章目录汇总 - 知乎 (zhihu.com)
内核版本:linux-6.1
个人仓库:
- 环境搭建脚本仓库:https://gitee.com/kingdix10/envsetup
- eel主仓库:https://gitee.com/kingdix10/eel
- eel改动仓库:https://gitee.com/kingdix10/eel-changes
- 驱动示例仓库:https://gitee.com/kingdix10/eel-kmodules
- 辅助工具仓库:https://gitee.com/kingdix10/eel-ctools
1. 总览
这里以ARM64为例。
在内核的起始阶段,还没有进程和线程的概念,在开启MMU之后,__primary_switched
的第一步就是将init_task的地址写到sp_el0,这个时候就可以用get_current()或者curent获取到0号线程的task_struct了。在0号线程的上下文,完成调度器的相关初始化之后,创建1号和2号线程,然后开启调度器,init_task自此进入idle状态。
这里看几个概念:
- 0号线程:对应init_task结构体,名字为swapper,在多处理器中,名称为
swapper/<id>
,负责内核的一些基础的初始化工作。 - 1号线程:由0号线程创建,最初的函数为kernel_init,运行在内核态,kernel_init完成一些初始化工作后,通过kernel_execve进入用户态。具体的名字由用户态程序决定。
- 2号线程:由0号线程创建,回调函数为
kthreadd
,名字也是kthreadd
,所有内核线程的创建都通过2号线程完成。也就是说,所有内核线程的父线程,都是kthreadd。
在kernel_init中,smp_init会为每个处理器核心创建一个的swapper线程,其task_struct结构体,并将其绑定到对应的处理器上。 在kernel_init调用的一些初始化函数中,有些会通过kthread或kworker的接口来创建内核线程,这些都内核线程的创建都由kthreadd接管。 在kernel_init最后,通过kernel_execve进入用户态,用户态的init程序,如busybox或systemd等,再通过fork或者clone等系统调用创建新的进程或者线程。
关于0号线程,在init_task中,设置的名字为swapper,在sched_init时,才会通过init_idle将其设置为swapper/<id>
,而这个id时bootcpu的id,大多数情况下,bootcpu的id是0,图中展示的就是这种情况。