linux软中断
来源:互联网 发布:网络教育文凭出国留学 编辑:程序博客网 时间:2024/06/08 09:42
linux中所谓的可延迟函数,包括软中断和tasklet以及通过中作队列执行的函数(这个以后说),软中断的分配是静态的(即值编译时定义),而tasklet的分配和初始化可以在运行时进行。
软中断
软中断所使用的数据结构定义为
static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp;
其中softirq_action类型为一个函数指针,从这里也可以看出,软中断的个数是有限的有NR_SOFTIRQS个,具体的定义如下:
enum{ HI_SOFTIRQ=0, TIMER_SOFTIRQ, NET_TX_SOFTIRQ, NET_RX_SOFTIRQ, BLOCK_SOFTIRQ, BLOCK_IOPOLL_SOFTIRQ, TASKLET_SOFTIRQ, SCHED_SOFTIRQ, HRTIMER_SOFTIRQ, RCU_SOFTIRQ, NR_SOFTIRQS};
可以看出,一共10个软中断。
struct softirq_action{ void (*action)(struct softirq_action *);};
软中断的初始化
void open_softirq(int nr, void (*action)(struct softirq_action *)){ softirq_vec[nr].action = action;}
上面函数中,参数nr为softirq_vec[]数组的下标,初始化就是初始化softirq_vec[]数组内容。
初始化了软中断后,要执行,接下来要做的是激活软中断,运用下面函数
void raise_softirq(unsigned int nr){ unsigned long flags; local_irq_save(flags); raise_softirq_irqoff(nr); local_irq_restore(flags); //恢复中断}
具体的激活工作由raise_softirq_irqoff函数实现
inline void raise_softirq_irqoff(unsigned int nr){ __raise_softirq_irqoff(nr); if (!in_interrupt()) wakeup_softirqd();/*唤醒本地的内核线程*/}
守护线程softirqd就是对软中断的处理
static int ksoftirqd(void * __bind_cpu){ set_current_state(TASK_INTERRUPTIBLE); while (!kthread_should_stop()) { preempt_disable();
if (!local_softirq_pending()) { preempt_enable_no_resched(); schedule(); preempt_disable(); } __set_current_state(TASK_RUNNING); while (local_softirq_pending()) {if (cpu_is_offline((long)__bind_cpu)) goto wait_to_die; do_softirq(); preempt_enable_no_resched(); cond_resched(); preempt_disable(); rcu_sched_qs((long)__bind_cpu); } preempt_enable(); set_current_state(TASK_INTERRUPTIBLE); } __set_current_state(TASK_RUNNING); return 0;wait_to_die: preempt_enable(); set_current_state(TASK_INTERRUPTIBLE); while (!kthread_should_stop()) { schedule(); set_current_state(TASK_INTERRUPTIBLE); } __set_current_state(TASK_RUNNING); return 0;}
下面是软中断的执行
asmlinkage void do_softirq(void){ __u32 pending; unsigned long flags; if (in_interrupt()) return; local_irq_save(flags); pending = local_softirq_pending(); if (pending) __do_softirq(); local_irq_restore(flags);}
具体由__do_softirq函数实现
asmlinkage void __do_softirq(void){ struct softirq_action *h; __u32 pending;
int max_restart = MAX_SOFTIRQ_RESTART; int cpu;
pending = local_softirq_pending(); account_system_vtime(current);__local_bh_disable((unsigned long)__builtin_return_address(0)); lockdep_softirq_enter(); cpu = smp_processor_id();restart: set_softirq_pending(0); local_irq_enable(); h = softirq_vec; do { if (pending & 1) { int prev_count = preempt_count(); kstat_incr_softirqs_this_cpu(h - softirq_vec); trace_softirq_entry(h, softirq_vec); h->action(h); trace_softirq_exit(h, softirq_vec); if (unlikely(prev_count != preempt_count())) { printk(KERN_ERR "huh, entered softirq %td %s %p" "with preempt_count x," " exited with x?\n", h - softirq_vec, softirq_to_name[h - softirq_vec], h->action, prev_count, preempt_count()); preempt_count() = prev_count; } rcu_bh_qs(cpu); } h++; pending >>= 1; } while (pending); local_irq_disable(); pending = local_softirq_pending(); if (pending && --max_restart) goto restart; if (pending) wakeup_softirqd(); lockdep_softirq_exit(); account_system_vtime(current); _local_bh_enable();}
到此,linux内核软中断的大致执行和实现基本上分析完了,中间有很多地方没有注释的,主要是考虑到需要别的实现机制以及有的比较易懂。能够自己看懂。
http://www.linuxso.com/linuxrumen/14467.html- linux软中断机制
- linux 2.6软中断
- linux软中断
- Linux中的软中断
- linux的软中断
- linux软中断机制
- linux软中断
- linux软中断
- linux软中断
- linux软中断
- linux tasklet/软中断
- linux 软中断
- linux软中断
- Linux软中断机制
- linux 补充原语, 中断,软中断
- linux中断控制之软中断
- [linux中断]——软中断机制
- linux中断源码分析 - 软中断(四)
- Linux驱动之设备模型(8)
- Linux驱动之设备模型(9)-platform
- i2c 知识点总结
- svn配置库各种图标提示的状态说明!超详细文字描述。
- Linux中断(interrupt)子系统之五…
- linux软中断
- poll, select &&nbs…
- Linux IIC驱动笔记
- new style I2C设备驱动…
- oracle
- poll机制分析
- ActiveMQ拦截器使用和原理
- uevent分析
- usb高速握手过程