前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【深入理解Linux内核锁】| 中断屏蔽

【深入理解Linux内核锁】| 中断屏蔽

作者头像
董哥聊技术
发布2023-08-29 16:38:28
4740
发布2023-08-29 16:38:28
举报
文章被收录于专栏:嵌入式艺术嵌入式艺术

【Linux内核锁】二、中断屏蔽

1、中断屏蔽思想

中断屏蔽,正如其名,屏蔽掉CPU的中断响应功能,解决并发引起的竞态问题。

在进入临界区前屏蔽中断,这么做有什么好处,以及有什么弊端?

好处在于

  • 保证在执行临界区代码时,不被中断所打断
  • 同时,系统的进程调度与中断息息相关,同时也限制了系统进程的并发,解决了系统进程并发带来的竞态问题。

弊端在于

  • Linux内核中,除了系统进程调度依赖中断,还有一些异步I/O等众多操作都依赖中断,因此长时间屏蔽中断是很危险的,会对系统造成严重影响,因此也要求临界区代码要简短。
  • 关闭中断能够解决进程调度、中断引发的竞态,但是这些都是单CPU内部的,对于SMP对称多处理器,仍然不可避免的会收到其他CPU的中断。因此,并不能解决SMPCPU引发的竞态

因此,单独使用中断屏蔽通常不是一种值得推荐的避免竞态的方法

2、Linux内核中断屏蔽的实现

2.1 Linux内核提供的API接口

关于中断屏蔽,Linux内核所提供的接口如下:

代码语言:javascript
复制
local_irq_enable()    // 使能本CPU的中断
local_irq_disable()    // 禁止本CPU的中断
local_irq_save(flags)   // 禁止本CPU的中断,并保存CPU中断位的信息
local_irq_restore(flags)  // 使能本CPU的中断,并恢复CPU中断位的信息
local_bh_disable(void)   // 禁止本CPU底半部中断
local_bh_enable(void)      // 使能本CPU底半部中断

2.2 API接口实现分析

因为中断屏蔽与底层芯片架构有关,不同架构处理方式不同,我们以ARM为例

2.2.1 local_irq_enable
代码语言:javascript
复制
#define local_irq_enable() do { raw_local_irq_enable(); } while (0)

#define raw_local_irq_enable()  arch_local_irq_enable()

#define arch_local_irq_enable arch_local_irq_enable
static inline void arch_local_irq_enable(void)
{
 asm volatile(
  " cpsie i   @ arch_local_irq_enable"
  :
  :
  : "memory", "cc");
}

函数介绍local_irq_enable函数用于将CPSR寄存器中的中断使能位设为1,从而使得CPU能够响应中断。

相关实现

asm:声明一个内联汇编表达式

cpsie i:汇编指令,设置CPSR寄存器的I位,来允许本CPU响应中断。

memory:向汇编说明,此处内存发生了更改,类似于内存屏障的作用

cc:表示可能会修改条件码的标志

汇编代码语法:https://www.jianshu.com/p/57fef17149ae

2.2.2 arch_local_irq_disable
代码语言:javascript
复制
#define arch_local_irq_disable arch_local_irq_disable
static inline void arch_local_irq_disable(void)
{
 asm volatile(
  " cpsid i   @ arch_local_irq_disable"
  :
  :
  : "memory", "cc");
}

函数介绍arch_local_irq_disable函数用于将CPSR寄存器中的中断使能位设为0,从而禁止CPU响应中断。

相关实现:同上

  • cpsid:是汇编指令,用于清除CPSR寄存器的中断标志,以禁止中断!
2.2.3 arch_local_irq_save
代码语言:javascript
复制
#define arch_local_irq_save arch_local_irq_save
static inline unsigned long arch_local_irq_save(void)
{
 unsigned long flags;

 asm volatile(
  " mrs %0, " IRQMASK_REG_NAME_R " @ arch_local_irq_save\n"
  " cpsid i"
  : "=r" (flags) : : "memory", "cc");
 return flags;
}

函数介绍arch_local_irq_save函数,用于保存当前中断状态并禁用中断。

相关实现

mrs %0 IRQMASK_REG_NAME_Rmrs指令将由IRQMASK_REG_NAME_R宏指定的IRQMASK寄存器的值移动到flags变量中。

2.2.4 arch_local_irq_restore
代码语言:javascript
复制
/*
 * restore saved IRQ & FIQ state
 */
#define arch_local_irq_restore arch_local_irq_restore
static inline void arch_local_irq_restore(unsigned long flags)
{
 asm volatile(
  " msr " IRQMASK_REG_NAME_W ", %0 @ local_irq_restore"
  :
  : "r" (flags)
  : "memory", "cc");
}

函数介绍arch_local_irq_restore函数,用于恢复当前中断状态并打开中断。

相关实现:同上

关于local_bh_disablelocal_bh_enable两个接口,涉及到中断底半部机制,内容较为复杂,放在后面单独拆解!

3、总结

该篇文章,主要了解以下几点:

  1. 中断屏蔽的思想
  2. 中断屏蔽的好处与不足
  3. Linux内核提供的中断屏蔽接口
  4. 中断屏蔽的基本汇编实现
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-05-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 嵌入式艺术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 【Linux内核锁】二、中断屏蔽
    • 1、中断屏蔽思想
      • 2、Linux内核中断屏蔽的实现
        • 2.1 Linux内核提供的API接口
        • 2.2 API接口实现分析
      • 3、总结
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档