Linux内核36-内核同步之禁止中断

简介: Linux内核36-内核同步之禁止中断

每一种技术的出现必然是因为某种需求。正因为人的本性是贪婪的,所以科技的创新才能日新月异。

今天,我们了解一下内核同步的最后一种方法,关闭中断。这是一种简单粗暴的方式,但行之有效。


1 禁止中断


作为嵌入式软件开发人员,对于禁止中断肯定不陌生。尤其是基于MCU的嵌入式软件,因为就一个微处理器核,所以禁止中断是实现临界代码段的有效手段。笔者比较熟悉的μC/OS-II或III,就是使用禁止中断保护临界代码段。当然了,这样的临界代码段一般较短,就几行代码而已。如果太长,会影响整个系统任务的调度,也有可能导致中断信号的丢失。

同样,Linux也不会放弃禁止中断这么好的同步机制。它保证内核控制路径可以继续执行,其访问的数据结构不会被中断处理程序破坏。但是,多核系统中,中断禁止是一个局部概念,也就是说,只是某一个CPU核中断被禁止,不能阻止运行在其它CPU上的中断处理程序访问要保护的数据结构。所以,在多核系统中,内核数据结构的保护一般是禁止中断搭配自旋锁一起使用。

local_irq_disable()利用cli汇编指令,禁止局部CPU的中断;local_irq_enable()利用sti汇编指令使能中断。正如在讲解”IRQ和中断”时所说的那样,cli和sti汇编指令,分别用来清除和设置eflags寄存器中的IF标志。

当内核代码进入临界代码段时,通过清除eflags寄存器中的IF标志实现禁止中断,从而保护临界代码段。但是,当内核离开临界代码段的时候,内核是否该恢复之前的IF标志呢?还是不做任何处理?显然,不做任何处理是不可以的,因为那样的话,就会丢失某些中断信号,这对于一个安全可靠的系统而言,是非常荒谬的。我们知道中断是以嵌套的方式被执行的,所以内核无需知道之前是什么具体的IF标志。只需要记录之前的标志值,在退出临界代码段的时候恢复之前的IF标志即可。

保存和恢复eflags内容,可以分别通过local_irq_save()和local_irq_restore()实现。local_irq_save拷贝eflags内容到一个局部变量中,然后调用cli指令清除IF标志。退出临界代码段的时候,local_irq_restore再把局部变量中的内容拷贝到eflags寄存器中。


2 禁止软中断


在讲软中断的时候,我们知晓可延时函数的执行时间是不可预测的(基本上都是在硬件中断处理程序终止的时候,因为软中断的实现大部分时候都是给tasklet服务的,而tasklet的用处就是协助硬件处理程序处理那些耗时长,又不是那么紧急的任务的)。因此,可延时函数要访问的数据结构必须被保护起来,防止竞态条件的产生。

可能很多人都想到了一个简单粗暴的方法,直接禁止那个CPU的中断不就可以了吗。没有中断处理程序被激活,软中断的行为也就不会发生混乱。

但是,事情不会那么简单,有时候,内核需要只禁止可延时函数,而不禁止中断。那怎么实现呢?

回忆do_softirq()函数,如果软中断计数器(存储在当前线程thread_info描述符的preempt_count成员中)是正数,它就不会处理软中断。所以,将这个计数器设为正数,软中断不会执行,在其上的所有可延时函数也不会执行。

local_bh_disable()给局部CPU的软中断计数器加1,local_bh_enable()则是将其减1。local_bh_disable()可以嵌套多调用几次,如果调用local_bh_enable()的次数匹配,可延时函数就会被使能。

为了确保及时执行长时间等待的线程,local_bh_enable()对软中断计数器执行减1操作之后,还有执行两个重要的操作:

  1. 检查preempt_count中的硬中断计数器和软中断计数器。如果都是0,且有挂起的软中断要执行,直接调用do_softirq()激活它们。
  2. 检查局部CPU的 TIF_NEED_RESCHED标志是否被设置;如果被设置,说明此时有进程正在请求调度,然后调用preempt_schedule()执行抢占调度。


3 总结


总之一句话,禁止中断包含禁止硬中断和软中断两种。禁止硬中断肯定就包含禁止软中断;但禁止软中断不会影响硬中断的响应。它们都有各自的使用场景。

相关文章
|
3月前
|
安全 网络协议 Linux
深入理解Linux内核模块:加载机制、参数传递与实战开发
本文深入解析了Linux内核模块的加载机制、参数传递方式及实战开发技巧。内容涵盖模块基础概念、加载与卸载流程、生命周期管理、参数配置方法,并通过“Hello World”模块和字符设备驱动实例,带领读者逐步掌握模块开发技能。同时,介绍了调试手段、常见问题排查、开发规范及高级特性,如内核线程、模块间通信与性能优化策略。适合希望深入理解Linux内核机制、提升系统编程能力的技术人员阅读与实践。
400 1
|
3月前
|
Ubuntu Linux
Ubuntu 23.04 用上 Linux 6.2 内核,预计下放到 22.04 LTS 版本
Linux 6.2 带来了多项内容更新,修复了 AMD 锐龙处理器设备在启用 fTPM 后的运行卡顿问题,还增强了文件系统。
|
3月前
|
Ubuntu Linux
Ubuntu 23.10 现在由Linux内核6.3提供支持
如果你想在你的个人电脑上测试一下Ubuntu 23.10的最新开发快照,你可以从官方下载服务器下载最新的每日构建ISO。然而,请记住,这是一个预发布版本,所以不要在生产机器上使用或安装它。
|
3月前
|
传感器 监控 Ubuntu
10 月发布,Ubuntu 23.10 已升级到 Linux Kernel 6.3 内核
硬件方面,Linux 6.3 引入了在 HID 中引入了原生的 Steam Deck 控制器接口,允许罗技 G923 Xbox 版赛车方向盘在 Linux 上运行;改善 8BitDo Pro 2 有线控制器的行为;并为一系列华硕 Ryzen 主板添加传感器监控。
|
3月前
|
Ubuntu Linux
Ubuntu24.04LTS默认采用Linux 6.8内核,实验性版本可通过PPA获得
IT之家提醒,当下的 Ubuntu 23.10 也是一个“短期支持版本”,该版本将在今年 7 月终止支持,而今年 4 月推出的 Ubuntu 24.04 LTS 长期支持版本将获得 5 年的更新支持。
|
3月前
|
监控 Ubuntu Linux
什么Linux,Linux内核及Linux操作系统
上面只是简单的介绍了一下Linux操作系统的几个核心组件,其实Linux的整体架构要复杂的多。单纯从Linux内核的角度,它要管理CPU、内存、网卡、硬盘和输入输出等设备,因此内核本身分为进程调度,内存管理,虚拟文件系统,网络接口等4个核心子系统。
293 0
|
3月前
|
Web App开发 缓存 Rust
|
3月前
|
Ubuntu 安全 Linux
Ubuntu 发行版更新 Linux 内核,修复 17 个安全漏洞
本地攻击者可以利用上述漏洞,攻击 Ubuntu 22.10、Ubuntu 22.04、Ubuntu 20.04 LTS 发行版,导致拒绝服务(系统崩溃)或执行任意代码。
|
3月前
|
Ubuntu 机器人 物联网
Linux Ubuntu 22.04 LTS 测试版实时内核已可申请
请注意,在启用实时内核后您需要手动配置 grub 以恢复到原始内核。更多内容请参考: