Linux内核抢占的理解

内核抢占功能

可抢占性,对一个系统的调度延时具有重要意义。2.6 之前,一个进程进入内核态后,别的进程无法抢占,只能等其完成或退出内核态时才能抢占, 这带来严重的延时问题,2.6 开始支持内核态抢占。

虽然内核支持了内核态抢占功能,但是也并非所有的内核路径都允许抢占,比如这几种情况都是需要禁止内核抢占的:

(1)内核执行中断处理例程时不允许内核抢占,中断返回时再执行内核抢占。
(2)当内核执行软中断或tasklet时,禁止内核抢占,软中断返回时再执行内核抢占。 
(3)在临界区禁止内核抢占,临界区保护函数通过抢占计数宏控制抢占,计数大于0,表示禁止内核抢占。

为保证Linux内核在以上情况下不会被抢占,抢占式内核使用了一个变量preempt_ count,称为内核抢占锁。这一变量被设置在进程的PCB结构task_struct中。每当内核要进入以上几种状态时,变量preempt_ count就加1,指示内核不允许抢占。每当内核从以上几种状态退出时,变量preempt_ count就减1,同时进行可抢占的判断与调度。抢占式Linux内核的修改主要有两点:

一是对中断的入口代码和返回代码进行修改。在中断的入口内核抢占锁preempt_count加1,以禁止内核抢占;在中断的返回处,内核抢占锁preempt_count减1,使内核有可能被抢占。另一基本修改是重新定义了自旋锁、读、写锁,在锁操作时增加了对preempt count变量的操作。在对这些锁进行加锁操作时preemptcount变量加1,以禁止内核抢占;在释放锁时preemptcount变量减1,并在内核的抢占条件满足且需要重新调度时进行抢占调度。

调度的时机

主动发生调度:

1)显式调用schedule()

用户态抢占时机:

 1. 从中断返回到用户空间user space:检查TIF_NEED_RESCHED是否为1
 2. 从系统调用返回到用户空间usersapce:检查TIF_NEED_RESCHED是否为1

内核态抢占的时机:

1) 中断返回内核空间:检查preempt_count是否为0和TIF_NEED_RESCHED是否为1。
当一个中断处理例程退出,在返回到内核态时(kernel-space)。这是隐式的调用schedule()函数,当前任务没有主动放弃CPU使用权,而是被剥夺了CPU使用权。
2)  显式或者隐式调preempt_enable()函数:检查preempt_count是否为0和TIF_NEED_RESCHED是否为1
这个隐式的调用,比如spin_unlock_bh和spin_unlock等,都会隐式的调用preempt_enable()函数,进而判断是否需要schedule。
3)使能软中断:检查preempt_count是否为0和TIF_NEED_RESCHED是否为1
使能软中断的函数local_bh_enable中会隐式包含对preempt_count的操作,所以会判断是否可以进行schedule。

需要注意:如果内核未使能内核态抢占,那么就调度时机就只能发生于用户态抢占或者主动调度的情况。

spinlock不允许睡眠,原因就是他设计初衷就是如此,因此在获取spinlock时就调用禁止抢占的函数,所以正常情况下获取锁的CPU是不会被抢占的,但如果工程师代码中进行了睡眠,那么睡眠会导致让出CPU,想象一下,一个低优先级的线程先获取了spinlock,如果来一个高优先级的线程去获取spinlock,就会一直获取不到导致死锁。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值