抢占和上下文切换

内容参考摘录自 《Linux内核设计与实现 第三版》
一、上下文切换
上下文切换,也就是从一个可执行进程切换到另一个可执行进程,由函数context_switch()函数负责处理。每当一个新的进程被选择出来准备投入运行的时候,schedule()就会调用该函数。完成两项基本工作。
在这里插入图片描述在这里插入图片描述
**·**调用switch_mm(),把虚拟内存从一个进程映射切换到新进程中
· 调用switch_to(),从上一个进程的处理器状态切换到新进程的处理器状态。<包括保存、恢复栈信息和寄存器信息>

因为内核必须知道在什么时候调用schedule()。如果仅靠用户程序代码显式地调用schedule(),它们可能就会永远的执行下去。相反,内核提供了一个need_resched标志来表明是否需要重新执行一次调度。当某个进程应该被抢占时,schedule_tick()就会设置这个标志;当一个优先级高的进程进入可执行状态的时候,try_to_wake_up()也会设置这个标志,内核检查该标志,确认其被设置,调用schedule()来切换到一个新的进程。
在这里插入图片描述
再返回用户空间以及中断返回的时候,内核也会检查need_resched标志。如果已经被设置,内核会在继续执行之前调用调度程序。
每个进程都包含一个need_resched标志,这是因为访问进程描述符内的数值要比访问一个全局变量快。

二、抢占
1.用户抢占
内核即将返回用户空间的时候,如果need_resched标志被设置,会导致schedule()被调用,此时就会发生用户抢占。在内核返回用户空间的时候,它知道自己是安全的,因为既然它可以继续去执行当前进程,那么它当然可以再去选择一个新的进程去执行。所以,内核无论是在中断处理程序还是在系统调用后返回,都会检查need_resched标志
抢占发生的两种情况
1>系统调用返回用户空间时
2>中断处理程序返回用户空间时

2.内核抢占
Linxu完整的支持内核抢占。在不支持内核抢占的内核中,内核代码可以一直执行,直到它完成为止。也就是说,调度程序没有办法在一个内核级的任务正在执行的时候重新调度——内核中的任务是以协作方式调度的,不具备抢占性。<在2.6版本以后的内核中,内核引入了抢占内力;现在,只要重新调度是安全的,内核就可以在任何时间抢占正在执行的任务。>
【注】只要没有持有锁,内核就可以进行抢占,锁是非抢占区域的标志。

为了支持内核抢占所做的第一处变动,就是为每个进程的thread_info引入preempt_count计数器。该计数器初始值为0,每当使用锁的时候数值就加1,释放锁的时候数值就减1。当数值为0的时候,内核就可执行抢占。从中断返回内核空间的时候,内核会检查need_resched和preempt_count的值。如果need_resched被设置,并且preempt_count为0的话,这说明有一个更为重要的任务需要执行,并且可以安全地抢占,此时,调度程序就会被调用。

内核抢占发生的情况
1>中断处理程序正在执行,且返回内核空间之前。
2>内核代码再一次具有可抢占性的时候。[释放锁的代码中会检查标志,并启动调度]
3>内核任务显示的调用schedule()。
4>内核自己阻塞的时候。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值