中断管理之下半部软中断

Linux中断管理中有个非常重要的设计理念就是上下半部机制
上半部就是硬件中断管理

中断设计为上下半部的原因如下
1.硬件中断处理程序以异步方式进行 它会打断其他重要的代码执行 因此为了避免被打断的程序停止时间太长 硬件中断处理程序必须尽快完成
2.硬件中断处理程序通常在关闭中断的情况下执行 关闭中断就是关闭本CPU的所有中断响应 关闭中断后 本地CPU就不能响应所有的中断响应 因此硬件中断处理程序必须尽快的完成

比如 在ARM处理器下 中断发生时 ARM处理器会自动的关闭IRQ/FIQ中断 知道从中断处理程序退出时才打开本地中断

上半部通常是完成整个中断处理任务中的一小部分 例如响应中断表明中断已经被软件接收 简单的数据处理 如DMA 以及硬件中断处理完成时发送EOI信号 给中断控制器等 下半部就是操作一些比较耗时的操作 比如数据复制 数据包的封装之类的 下半部执行的关键点是允许响应所有的中断 是一个开中断的环境

对于中断下半部分
目前只有块设备和网络子系统使用了软中断类型 tasklet机制也是软中断类型中的一种
Linux中定义的软中断类型如下

include/linux/interrupt.h
enum
{
HI_SOFTIRQ=0, //最高优先级的软中断类型
TIMER_SOFTIRQ,//Timer定时器的软中断
NET_TX_SOFTIRQ,//发送网络数据包的软中断
NET_RX_SOFTIRQ,//接收网络数据包的软中断
BLOCK_SOFTIRQ,//块设备软中断
BLOCK_IOPOLL_SOFTIRQ,
TASKLET_SOFTIRQ,//专门为tasklet机制准备的软中断
SCHED_SOFTIRQ,//进程调度以及负载均衡
HRTIMER_SOFTIRQ, /* Unused, but kept as tools rely on the // 高精度定时器
numbering. Sigh! */
RCU_SOFTIRQ, //专门为RCU服务的软中断

NR_SOFTIRQS //最多支持的软中断类型的数目 这里是10

};

softirq_action结构体 当触发软中断时 触发这个action函数的执行
struct softirq_action
{
void (action)(struct softirq_action );
};

中断描述符数组 软中断的索引号就是该数组的索引
static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp;

中断状态信息
typedef struct {
unsigned int __softirq_pending;
} ____cacheline_aligned irq_cpustat_t;

注册软中断API
void open_softirq(int nr, void (action)(struct softirq_action ))
{
softirq_vec[nr].action = action;
}
这个nr就是TASKLET_SOFTIRQ或者其他 linux定义了十种

触发软中断API
void raise_softirq(unsigned int nr)
{
unsigned long flags;

local_irq_save(flags);  //保存中断  标志位 我也不知道有什么用
raise_softirq_irqoff(nr);
local_irq_restore(flags);

}

inline void raise_softirq_irqoff(unsigned int nr)
{
__raise_softirq_irqoff(nr);

/*
 * If we're in an interrupt or softirq, we're done
 * (this also catches softirq-disabled code). We will
 * actually run the softirq once we return from
 * the irq or softirq.
 *
 * Otherwise we wake up ksoftirqd to make sure we
 * schedule the softirq soon.
 */
if (!in_interrupt())  //判断是否在进程上下文中  
    wakeup_softirqd();

}
if (!in_interrupt())只是判断是否在进程上下文中 如果在进程上下文中就调用wakeup_softirqd();来唤醒ksoftirqd内核线程来处理 如果在中断上下文中 只需要设置本地CPU __

void __raise_softirq_irqoff(unsigned int nr)
{
trace_softirq_raise(nr);
or_softirq_pending(1UL << nr);
}

void __raise_softirq_irqoff(unsigned int nr)
{
trace_softirq_raise(nr);
or_softirq_pending(1UL << nr);
}

#define or_softirq_pending(x) (local_softirq_pending() |= (x))
#define local_softirq_pending() \
__IRQ_STAT(smp_processor_id(), __softirq_pending)
#define __IRQ_STAT(cpu, member) (irq_stat[cpu].member)

替换也即是irq_stat[cpu].__softirq_pending|= (1<

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值