Linux进程调度——schedule()函数分析

本文详细分析了Linux内核中进程调度的关键函数schedule()的执行流程,从schedule()开始,通过sched_submit_work()避免死锁,再到__schedule()实现进程切换。在__schedule()中,重点讲解了context_switch()和switch_to()如何完成进程上下文的保存与恢复,涉及内核抢占、栈保护等核心概念。最后,总结了schedule()的整体执行流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

刘森林 原创作品转载请注明出处 《Linux内核分析》MOOC课程
打开终端中输入qemu –kernel linux-3.18.6/arch/x86/boot/bzImage –initrd rootfs.img –S –s
然后打开另一个终端输入

gdb
(gdb)file linux-3.18.6/vmlinux
(gdb)target remote:1234
(gdb)b schedule
(gdb)c

进行调试跟踪schedule的执行过程。

这里写图片描述
进程调度时,首先进入schedule()函数,将一个task_struct结构体的指针tsk赋值为当前进程。
然后调用sched_submit_work(tsk)
我们进入这个函数,查看一下做了什么工作
我们在执行到sched_submit_work时,输入si进入函数。
这里写图片描述
可以看到这个函数时检测tsk->state是否为0 (runnable)若为运行态时则返回,
tsk_is_pi_blocked(tsk),检测tsk的死锁检测器是否为空,若非空的话就return。
这里写图片描述
然后检测是否需要刷新plug队列,用来避免死锁。
sched_submit_work主要是来避免死锁。
然后我们进入__schedule()函数。
这里写图片描述
__schedule()是切换进程的真正代码,我们来分析一下具体的关键代码

  • 1.创建一些局部变量
struct task_struct *prev, *next;//当前进程和一下个进程的进程结构体
unsigned long *switch_count;//进程切换次数
struct rq *rq;//就绪队列
int cpu;
  • 2.关闭内核抢占,初始化一部分变量
need_resched:
preempt_disable();//关闭内核抢占
cpu = smp_processor_id();
rq = cpu_rq(cpu);//与CPU相关的runqueue保存在rq中
rcu_note_context_switch(cpu);
prev = rq->curr;//将runqueue当前的值赋给prev
  • 3.选择next进程
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值