linux --- 0号进程,1号进程,2号进程
0号进程
0号进程称为 idle 进程,其 pid 等于0。
每个进程都有一个进程控制块PCB(Process Control Block),PCB的数据结构类型是struct task_struct。idle进程对应的PCB是 struct task_struct init_task。
idle进程是唯一一个没有通过fork或者kernel_thread产生的进程,因为 init_task 是静态变量(初始化了的全局变量),其他进程的PCB都是fork或者kernel_thread动态申请内存创建的。
每个进程都有对应的一个函数,idle进程的函数是 start_kernel(),因为进入该函数前,栈指针SP已经指向 init_task 的栈顶了,处于什么进程,看SP指向哪个进程的栈。
init_thread_union + THREAD_START_SP 即为栈顶
start_kernel() 最后会调用 cpu_startup_entry() ,其内部是 while(1) {},永不退出。
在smp系统中,每个处理器单元有独立的一个运行队列,而每个运行队列上又有一个idle进程,即有多少处理器单元,就有多少idle进程。系统的空闲时间,其实就是指idle进程的”运行时间”。
core0上的idle进程由init_task进程退化而来,而AP的idle进程则是BSP在后面调用fork()函数逐个创建的?

idle进程的运行时机
idle 进程优先级为MAX_PRIO,即最低优先级。早先版本中,idle是参与调度的,所以将其优先级设为最低,当没有其他高优先级进程可以运行时,才会调度执行 idle。而目前的版本中 idle 并不在运行队列中参与调度,而是在运行队列结构中含idle指针,指向idle进程,在调度器发现运行队列为空的时候运行,调入运行。
1号进程
1号进程称为 init 进程,其 pid 等于1。
1号进程是0号进程通过调用 kernel_thread() 创建的,在运行 schedule_preempt_disabled() 内的 schedule() 后,就启动调度器进行进程切换,kernel_init() 也就得以运行。
kernel_init() 最后会启动用户态的处于根文件系统存储的 init 进程,从而实现 init 内核态到 init 用户态的转化。
init进程完成系统的初始化,是系统中所有其它用户进程的祖先进程。
内核态init进程的功能
kernel_init()--->kernel_init_freeable()--->prepare_namespace():挂在根文件系统。uboot会把根文件系统所在的分区传给linux,比如“root=/dev/mmcblk1p2 rootwait rw”就表示根文件系统在/dev/mmcblk1p2 中,也就是 SD卡控制器2控制的SD卡或EMMC等设备的分区 2 中。细节可查看博客:
2号进程
2号进程称为 kthreadd 进程,其 pid 等于2。
kthreadd进程由idle进程通过kernel_thread创建,并始终运行在内核空间, 负责所有内核线程的创建。
kthreadd利用for(;;)一直驻留在内存中运行:主要过程如下:
- 检查kthread_create_list为空时,kthreadd让出cpu的执行权
- kthread_create_list不为空时,利用while循环遍历kthread_create_list链表
- 每取下一个链表节点后调用create_kthread,创建内核线程
内核线程的创建通过API:kthread_run()
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
2016-02-04 JavaWeb开发---------------Tomcat服务器学习