local_irq_save与local_irq_disable
来源:互联网 发布:41478 网络电视直播 编辑:程序博客网 时间:2024/05/17 04:03
void local_irq_save(unsigned long flags);
void local_irq_disable(void);
对 local_irq_save的调用将把当前中断状态保存到flags中,然后禁用当前处理器上的中断发送。注意, flags 被直接传递, 而不是通过指针来传递。 local_irq_disable不保存状态而关闭本地处理器上的中断发送; 只有我们知道中断并未在其他地方被禁用的情况下,才能使用这个版本。
可通过如下函数打开中断:
void local_irq_restore(unsigned long flags);
void local_irq_enable(void);
第一个版本将local_irq_save保存的flags状态值恢复, 而local_irq_enable无条件打开中断. 与 disable_irq不同, local_irq_disable不会维护对多次的调用的跟踪。 如果调用链中有多个函数需要禁止中断, 应该使用local_irq_save.
在2.6内核, 没有方法全局禁用整个系统的所有中断。 内核开发者认为关闭所有中断的代价太高,因此没有必要提供这个能力。如果读者使用的老驱动程序调用了类似cli和sti这样的函数,为了该驱动程序能够在2.6下使用,则需要进行修改而使用正确的锁。
in_interrupt()是判断当前进程是否处于中断上下文,这个中断上下文包括底半部和硬件中断处理过程,
函数实现:
#define in_interrupt() ({ const int __cpu = smp_processor_id(); /
(local_irq_count(__cpu) + local_bh_count(__cpu) != 0); })
判断中断计数和底半部计数是否〉0,如果只希望判断是否在硬件中断上下文,则可以使用:in_irq()。
local_irq_disable() , local_irq_enable() , local_irq_save() 和 local_irq_restore() 为中断处理函数,主要是在要进入临界区时禁止中断和在出临界区时使能中断。local_irq_disable() 和 local_irq_enable() 配对使用;而 local_irq_save() 则和 local_irq_restore() 配对使用。
local_irq_disable() 和 local_irq_save() 都可以禁止中断,但不同的是后者可以保存中断状态。
local_irq_restore() 在使能中断的同时还恢复了由 local_irq_save() 所保存的中断状态。
这 4 个宏定义在 include/linux/Irqflag.h 中:
#define local_irq_enable() \
do { trace_hardirqs_on(); raw_local_irq_enable(); } while (0)
#define local_irq_disable() \
do { raw_local_irq_disable(); trace_hardirqs_off(); } while (0)
#define local_irq_save(flags) \
do { raw_local_irq_save(flags); trace_hardirqs_off(); } while (0)
#define local_irq_restore(flags) \
do { \
if (raw_irqs_disabled_flags(flags)) { \
raw_local_irq_restore(flags); \
trace_hardirqs_off(); \
} else { \
trace_hardirqs_on(); \
raw_local_irq_restore(flags); \
} \
} while (0)
其中,raw_local_irq_disable() 在 include/asm-i386/Irqflag.h定义为:
static inline void raw_local_irq_disable(void){ native_irq_disable(); }
从 native_irq_disable() 的名字可以看到是”禁止本地中断“ 。禁止本地中断并不保护运行在另一个CPU上的中断处理程序对该数据结构的并发访问。native_irq_disable() 同样定义在 include/asm-i386/Irqflag.h 中:
static inline void native_irq_disable(void){ asm volatile("cli": : :"memory");}
指令 cli 会清除 eflags 控制寄存器中的IF标志,这样就禁止了中断。
同样可以看到 local_irq_enable() 的最终定义为:
static inline void native_irq_enable(void){ asm volatile("sti": : :"memory");}
指令 cli 会设置 eflags 控制寄存器中的IF标志,这样就使能了中断。
有时候,为了避免中断处理程序对 eflags 寄存器内容的破坏,在进入临界区时使用 local_irq_save() 来保存 eflags 寄存器(将 elfags 保存在一个变量中)以及在出临界区时用 local_irq_restore() 来恢复 eflags 寄存器。同样在include/asm-i386/Irqflag.h 有定义:
对应于 local_irq_save() 有:
static inline unsigned long native_save_fl(void){ unsigned long f; asm volatile("pushfl ; popl %0":"=g" (f): /* no input */); return f;}
上面,先将 eflags 压入栈中,然后再弹出到 f 变量中将其保存起来。
对应于 local_irq_restore() 有:
static inline void native_restore_fl(unsigned long f){ asm volatile("pushl %0 ; popfl": /* no output */ :"g" (f) :"memory", "cc");}
上面,将变量 f 压入栈,然后弹到 eflags 中。另外,cc 是因为汇编指令会修改 eflags 寄存器时而采用。
对于单 CPU,非抢占的情况,假如有:
local_irq_disable()
/* 临界区代码 */
local_irq_enable()
这里,如果当执行到 local_irq_disable() 时,中断已经被禁止。那么在退出临界区时,再执行 local_irq_enable() 时会使所有的中断都打开,这样是可能带来副作用的,修正这种情况的办法是使用 local_irq_save() 和 local_irq_restore()。
- local_irq_save与local_irq_disable
- local_irq_save和 local_irq_disable
- local_irq_save 与 local_irq_restore
- local_irq_save
- local_irq_disable与local_irq_enable
- local_irq_disable
- local_irq_disable
- local_irq_disable
- local_irq_disable
- local_irq_disable,irq_disable与disable_irq的区别
- 互斥与同步——local_irq_enable与local_irq_disable
- 互斥与同步——local_irq_enable与local_irq_disable
- start_kernel——local_irq_disable
- local_bh_disable, preempt_disable, local_irq_disable
- local_irq_disable和disable_irq的区别
- local_irq_enable和local_irq_disable是消除异步并发源的有效方式
- 与
- 与
- 导出csv
- Cacti完全使用手册 ( 让你快速个性化使用Cacti )
- 编写CppUnit测试用例
- html转pdf 格式不变
- 09-Scrum过程-评审会(Review Meeting) & 反思会(Retrospective Meeting)
- local_irq_save与local_irq_disable
- 关注的 网易公开课
- 基于MFC的Cppunit测试用例编写步骤
- MYSQL创建utf-8格式的数据库
- 01-Scrum 概述 ,02-橄榄球 VS 软件,03-Scrum敏捷方法一分钟扫盲 ,04-Scrum敏捷方法中的工作产品 ,05-Scrum敏捷方法中的角色,06-Scrum过程-创建和维护产品
- Jquery 放大镜效果
- 一些英文
- 在eclipse中配置hadoop插件
- Mvc下异步断点续传大文件