preempt_disable宏

本文深入探讨Linux内核的抢占式调度机制,包括关键数据结构thread_info、抢占计数器preempt_count的作用,以及常见调度点如进程阻塞、参数调整、睡眠进程唤醒等。同时,介绍了显式和隐式调度的区别,以及禁用和使能抢占的典型场景与函数。

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

1.相关数据结构及函数如下:

struct thread_info中
{
        unisgned int preempt_count;//线程抢占引用计数器,为0才能被抢占
}


2.preempt_disable的定义

#define preempt_disable() \
do{ \
        inc_preempt_count(); \//增加preempt_count
        barrier();    \//内存屏障
}while(0)


3.barrier:内存屏障
      内存屏障出现因为编译器gcc或现在的处理器常会自作聪明地对指令序列进行一些处理,比如数据缓存,读写指令乱序执行等等。如果优化对象是普通内存,那么一般会提升性能而且不会产生逻辑错误。但如果对 I/O操作进行类似优化很可能造成致命错误。
4. 常见的调度点
      1)进程被阻塞时比如申请资源时被阻塞
      2)调整参数时   比如通过sched_setscheduler() ,nice()等函数调整进程的调度策略,静态优先级时
      3)睡眠进程被唤醒时:比如wake_up唤醒等待队列中的进程时,如果该进程具有更高优先级则会设置当前进程TIF_NEED_RESCHED,如果允许内核态抢占,则会调度一次
      4)中断处理完时  如果中断处理过程中设置了TIF_NEED_SCHED标志,中断返回时,不论是要返回内核态还是用户态,都会发生一次抢占。当然,在这也会检查有没有软中断需要处理。
      5)执行了preempt_enable()函数。
5. linux下有两种调度方式:
      1)显式调度,进程自己因为缺少相应的所申请的资源,显式调用调度器,让出处理器,比如:内核申请的信号阻塞了,自旋锁锁住了。
      2)隐式调度,整个linux系统在运行过程中的非显示的调用调度器,这又分两种情况:
        A)用户态抢占调度  比如:在系统调用,中断处理,异常处理返回用户态时,该进程的时间片已经用完。
         B)内核态抢占调度  比如:当前内核态执行过程中事先没有禁止内核态抢占,有中断产生时,中断处理 又产生了更高级优先进程,那么就会直接抢占前面的内核态执行体。
6. 抢占式内核中有三处地方需要显示的禁用抢占:
      1) 操作Per-CPU变量的时候,比如smp_processor_id()就是这一类问题,但一个进程被抢占后重新调度,有可能调度到其他的CPU上去,这时定义的Per-CPU变量就会有问题。下面是一个例子:
      2) 必须保护CPU的状态。这类问题是体系结构依赖的。例如,在x86上,进入和退出FPU就是一种临界区,必须在禁抢占的情况下使用。
      3) 获得和释放锁必须在一个进程中实现。也就是说一个锁被一个进程持有,也必须在这个进程中释放。
7.禁用/使能抢占的函数主要有:
      1)spin_lock()/spin_unlock()  spin_lock_irq()/spin_unlock_irq()
      2)disable_preempt()/enable_preempt()(禁止或使能内核抢占)调用下面的inc_preempt_count()/dec_preempt_count(),并且加入了memory barrier。
     3)inc_preempt_count()/dec_preempt_count()
     4)get_cpu()/put_cpu()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值