Linux内核零碎笔记

来源:网络 责任编辑:栏目编辑 发表时间:2013-07-01 09:01 点击:

#中断下半部.
common_interrupt: 
addl $-0x80,(%esp) /* Adjust vector into the [-256,-1] range */  #调整中断号到0~255的范围.
SAVE_ALL
TRACE_IRQS_OFF
movl %esp,%eax
call do_IRQ  #处理中断例程.
jmp ret_from_intr
ENDPROC(common_interrupt)

unsigned int __irq_entry do_IRQ(struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);

/* high bit used in ret_from_ code */
unsigned vector = ~regs->orig_ax;
unsigned irq;

exit_idle();
irq_enter();

irq = __get_cpu_var(vector_irq)[vector];

if (!handle_irq(irq, regs)) {  #调用对应的中断例程.
ack_APIC_irq();  #如果例程成功返回则回应8259A高级编程中断控制器.

if (printk_ratelimit())
pr_emerg("%s: %d.%d No irq handler for vector (irq %d)\n",
__func__, smp_processor_id(), vector, irq);
}

irq_exit();  #处理完中断上半部后,就调用irq_exit执行中断下半部.

set_irq_regs(old_regs);
return 1;
}

void irq_exit(void)
{
account_system_vtime(current);
trace_hardirq_exit();
sub_preempt_count(IRQ_EXIT_OFFSET);
if (!in_interrupt() && local_softirq_pending())
invoke_softirq();  #调用__do_softirq.

rcu_irq_exit();
#ifdef CONFIG_NO_HZ
/* Make sure that timer wheel updates are propagated */
if (idle_cpu(smp_processor_id()) && !in_interrupt() && !need_resched())
tick_nohz_stop_sched_tick(0);
#endif
preempt_enable_no_resched();
}

# define invoke_softirq() __do_softirq()  #invoke_softirq是替换成__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();  #保存待处理的软中断的32位图到栈变量里.
account_system_vtime(current);

__local_bh_disable((unsigned long)__builtin_return_address(0));
lockdep_softirq_enter();

cpu = smp_processor_id();
restart:
/* Reset the pending bitmask before enabling irqs */
set_softirq_pending(0);  #清零待处理的软中断的32位图.

local_irq_enable();  #当前CPU开启中断.

h = softirq_vec;  #获取软中断数组的第一个元素.

do {  #开始轮询软中断数组.好像是32个.
if (pending & 1) {  #判断每一位,为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 %08x,"
" exited with %08x?\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();  #当前CPU屏蔽中断.

pending = local_softirq_pending();  #再获取一下待处理的软中断的32位图,看处理软中断期间是否又发生了软中断请求.
if (pending && --max_restart)  #如果发生请求并且在单次处理软中断的最大循环检查次数内.
goto restart;  #则跳到restart处,再处理新来的软中断.可见软中真是响应的非常及时呀.

if (pending)  #如果如果软中断的次数确实太频繁了.
wakeup_softirqd();  #则唤醒专门处理软中断的内核线程.

lockdep_softirq_exit();

account_system_vtime(current);
_local_bh_enable();
}

#软中断_32位的位图判断 并行(SMP情况下同时处理) 内核线程辅助检测软中断位图 不可睡眠
#tasklet 

    发表评论
    请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
    用户名: 验证码:点击我更换图片
    最新评论 更多>>

    推荐热点

    • /etc/fstab 详解
    • nginx主主集群
    •  LVS-NAT和LVS-DR模式的实现详解
    •  RHCE考试之磁盘配额
    • 学习笔记:ACL详解
    •  LVM逻辑卷管理器
    • suse linux双网卡双网关配置
    •  Nginx主主负载均衡架构
    • ubuntu学习Mysql

    快速直达

    操作系统导航

    LinuxWindows虚拟机
    网站首页 - 友情链接 - 网站地图 - TAG标签 - RSS订阅 - 内容搜索
    Copyright © 2008-2015 计算机技术学习交流网. 版权所有

    豫ICP备11007008号-1