0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

哪些关闭了Linux抢占?抢占又关闭了谁?

Linux阅码场 来源:未知 作者:胡薇 2018-05-04 08:57 次阅读

本文对比分析:

preempt_disable()

local_irq_disable()/local_irq_save(flags)

spin_lock()

spin_lock_irq()/spin_lock_irqsave(lock, flags)

哪些关闭了抢占?另外,再说清楚,抢占又关闭了谁。

首先,把这几个API的关系图再勾勒一下。

我们理解,spin_lock()会调用preempt_disable() 导致本核的抢占调度被关闭(preempt_disable函数实际增加preempt_count来达到此效果),其次我们理解spin_lock_irq()是local_irq_disable()+preempt_disable()的合体。

下面一幅图描述了几个函数之间的包含关系如下:

local_irq_disable()/local_irq_save()的disable和save版的唯一区别是,要不要保存CPU对中断的屏蔽状态。

spin_lock_irq()/spin_lock_irqsave(lock, flags)的唯一区别是,要不要保存CPU对中断的屏蔽状态。

是谁杀了抢占?

Kernel的代码明确显示,执行抢占调度的时候,会同时检测“non-zero preempt_count or interrupts are disabled”:

我们可以进一步展开preemptible():

对于ARM处理器而言,判断irqs_disabled(),其实就是判断CPSR中的IRQMASK_I_BIT是否被设置。

所以,我们得出一个结论,前言这一节里面,列出的所有函数,都能关闭本核的抢占调度。因为,无论是preempt_count计数状态,还是中断被关闭,都会导致kernel认为无法抢占!

通杀逻辑如下:

杀手的差异在哪里?

既然都关闭了抢占,那么区别在哪里呢?

我们看两段代码,假设下面的代码都发生在NICE为0的普通进程:

preempt_disable()

xxx(1)

preempt_enable()

local_irq_disable()

xxx(2)

local_irq_enable()

首先,xxx(1)和xxx(2)里面,都是不可以抢占的。一个搞定了preempt_count,一个搞定了中断。

但是假设xxx(1)内唤醒了一个高优先级的RT任务,那么在preempt_enable()的时刻,直接就是一个抢占点,这个时候,发生schedule,高优先级RT任务进来跑;假设xxx(2)内唤醒了一个高优先级的RT任务,那么在local_irq_enable()的时刻,不是一个抢占点,高优先级RT的任务必须等待下一个抢占点。下一个抢占点,可能是时钟tick处理返回、中断返回、软中断结束、yield()等等多种情况。

在preempt_enable()中,会执行一次preempt_schedule():

而local_irq_enable()只是单纯的开启CPU对中断的响应,对于ARM而言,它就是:

再来看大boss,spin_lock_irq是同时调用了preempt_disable和local_irq_disable:

而对应的spin_unlock_irq()则同时调用了local_irq_enable()和preempt_enable():

大家想一想,为何preempt_enable()比local_irq_enable()后发生呢?如果代码顺序是这样的:

preempt_enable()

local_irq_enable()

第一句preempt_enable()想执行抢占调度的话,即便调用了preempt_schedule(),但是由于IRQ还是关门的,preempt_schedule()函数会立即返回(详见《是谁杀了抢占?》一节),所以无法抢占;后一句local_irq_enable()不会执行抢占调度。所以,如果这么干的话,

spin_lock_irq()

xxx(3)

spin_unlock_irq()

如果xxx(3)唤醒了高优先级的RT,在spin_unlock_irq()的时刻,将无法直接抢占!

还好,真正的顺序是:

local_irq_enable()

preempt_enable()

所以,在spin_unlock_irq()的时刻,RT进程就换入执行了。

看小一点的boss,spin_lock():

spin_lock()

xxx(4)

spin_unlock()

如果xxx(4)唤醒了RT进程,在spin_unlock()的时刻,会立即抢入。因为spin_unlock()会调用preempt_enable()。

而抢占又杀了谁?

理论上,关抢占,并没有彻底的关闭调度器,因为进程还是可以主动地sleep:

上述代码,在spin_lock的区间里面,调用了msleep(),这个时候,不属于抢占,Linux还是会pick下一个task来跑。

不过这样的代码,一般在后期蕴藏着巨大的风险,导致后期的莫名崩溃。所以呢,实际的工程里面,我们是严格地禁止的。

建议大家打开Kernel里面的config里面的DEBUG_ATOMIC_SLEEP,一旦出现这种情况,让kernel去汇报错误。

这种情况下,kernel检测到有人在atomic上下文里面执行可能睡眠的行为,会直接报执行的栈回溯。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • cpu
    cpu
    +关注

    关注

    68

    文章

    10802

    浏览量

    210771
  • Linux
    +关注

    关注

    87

    文章

    11202

    浏览量

    208693
  • API
    API
    +关注

    关注

    2

    文章

    1471

    浏览量

    61742

原文标题:宋宝华: 是谁关闭了Linux抢占,而抢占又关闭了谁?

文章出处:【微信号:LinuxDev,微信公众号:Linux阅码场】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    gd32vf103根据例子配置systick和adc中断,但是adc中断无法抢占systick是为什么?

    根据例子配置systick和adc中断,但是adc中断无法抢占systick 配置为向量和非相量都没有实现
    发表于 01-10 07:43

    MPLS LSP隧道抢占

    MPLS LSP隧道抢占
    发表于 05-30 15:26

    Linux内核抢占和用户抢占的概念和区别

    本文详解了Linux内核抢占实现机制。首先介绍内核抢占和用户抢占的概念和区别,接着分析不可
    发表于 08-05 08:18

    详解Linux内核抢占实现机制

    本文详解了Linux内核抢占实现机制。首先介绍内核抢占和用户抢占的概念和区别,接着分析不可
    发表于 08-06 06:16

    嵌入式Linux实时化技术详谈

    Linux内核设计中,中断可以抢占最高优先级的任务,使高优先级任务被阻塞的最长时间不确定。而且,由于内核为保护临界区需要关闭中断,更加增长了高优先级任务阻塞时间。  ● 时钟精度  Linux
    发表于 08-03 07:00

    苹果更新,教你关闭iPhone手机系统更新

    近期,苹果更新10.2的系统,对部分粉丝来说是好事儿,但是有很多苹果手机用户并不想更新系统,但是总是会有一个烦人的小红点提醒。那么,如何关闭苹果手机的系统更新呢?
    发表于 12-19 14:22 3.8w次阅读

    谷歌针对位置记录问题更新 可以彻底关闭

    。 对此谷歌近日针对这一问题进行了更新,更新内容显示,如果位置记录项目被关闭,那么位置信息就不再会得到保存
    的头像 发表于 08-25 10:04 4249次阅读

    Linux开放端口和关闭端口的方法

    Linux开放端口和关闭端口的方法如下
    发表于 05-18 09:14 1w次阅读
    <b class='flag-5'>Linux</b>开放端口和<b class='flag-5'>关闭</b>端口的方法

    linux的端口怎么关闭

    怎么关闭linux的端口?下面本篇文章给大家介绍一下linux下查看端口是否打开、关闭/打开端口的方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。
    发表于 05-29 09:27 4027次阅读
    <b class='flag-5'>linux</b>的端口怎么<b class='flag-5'>关闭</b>

    Linux阅码场原创精华文章分享,你值得拥有

    技术的前世今生之前世 郭健:Linux进程调度技术的前世今生之今生 宋宝华:是关闭Linux抢占
    的头像 发表于 10-10 16:28 2698次阅读

    Linux中内核抢占相关的基础知识

    今天要分享的是抢占相关的基础知识。本文以内核抢占为引子,概述一下 Linux 抢占的图景。我尽量避开细节问题和源码分析。 什么是内核抢占
    的头像 发表于 11-09 16:48 2001次阅读

    关闭Linux抢占

    我们理解,spin_lock()会调用preempt_disable() 导致本核的抢占调度被关闭(preempt_disable函数实际增加preempt_count来达到此效果),其次我们理解spin_lock_irq()是local_irq_disable()+pr
    发表于 08-07 17:19 868次阅读
    是<b class='flag-5'>谁</b><b class='flag-5'>关闭</b><b class='flag-5'>了</b><b class='flag-5'>Linux</b><b class='flag-5'>抢占</b>?

    Linux下如何开启、关闭端口

    查看防火墙状态 在Linux控制台输入:firewall-cmd --state 此时控制台返回:not running表示防火墙处于关闭状态
    的头像 发表于 05-12 14:54 5583次阅读
    <b class='flag-5'>Linux</b>下如何开启、<b class='flag-5'>关闭</b>端口

    操作系统中抢占式和非抢占式内核的区别

    操作系统一般分为抢占式内核和非抢占式内核,通常RTOS都是抢占式内核。你知道抢占式内核和非抢占式内核的区别吗?
    的头像 发表于 05-29 10:47 1664次阅读
    操作系统中<b class='flag-5'>抢占</b>式和非<b class='flag-5'>抢占</b>式内核的区别

    linux关闭docker的命令

    Linux 系统中,关闭 Docker 的操作可以通过以下多种方式进行。本文将详细讲解每一种方式,并提供示例代码和命令,以帮助读者更好地理解和实践。 使用 docker 命令 最常用的方法
    的头像 发表于 11-23 09:39 2697次阅读