超强的Linux中断分析

上传人:re****.1 文档编号:498134384 上传时间:2023-02-05 格式:DOC 页数:13 大小:98KB
返回 下载 相关 举报
超强的Linux中断分析_第1页
第1页 / 共13页
超强的Linux中断分析_第2页
第2页 / 共13页
超强的Linux中断分析_第3页
第3页 / 共13页
超强的Linux中断分析_第4页
第4页 / 共13页
超强的Linux中断分析_第5页
第5页 / 共13页
点击查看更多>>
资源描述

《超强的Linux中断分析》由会员分享,可在线阅读,更多相关《超强的Linux中断分析(13页珍藏版)》请在金锄头文库上搜索。

1、1) IPI 中断的初始化。intr_init_hook 调 用 apic_intr_init() , smp_intr_init() ,这 个 函 数 设置 IPI 中 断 的 处 理, SPURIOUS_APIC_VECTOR 和ERROR_APIC_VECTOR 设置 ISR 。后者再调用 如果 CONFIG_SMP然 后 , apic_intr_init() 为 另 外 两 个 IPI :2) irq_descNR_IRQSstruct irq_desc,亦即 irq_desc_t,描述了一个 irq 的属性,女口 irqaction、depth、pending_mask 等。incl

2、ude/linux/irq.h:struct irq_desc irq_flow_handler_t handle_irq;struct irq_chip*chip;struct msi_desc*msi_desc;void*handler_data;void*chip_data;struct irqaction *action; /* IRQ action list */ unsigned intstatus;/* IRQ status */unsigned intdepth;/* nested irq disables */unsigned intwake_depth; /* nested

3、 wake enables */unsigned intirq_count; /* For detecting broken IRQs */unsigned intirqs_unhandled;spinlock_tlock;#ifdef CONFIG_SMPcpumask_taffinity;unsigned intcpu;#endif|#ifdefined(CONFIG_GENERIC_PENDING_IRQ)defined(CONFIG_IRQBALANCE)cpumask_tpending_mask;#endif#ifdef CONFIG_PROC_FS struct proc_dir_

4、entry *dir;#endif const char *name; cacheline_internodealigned_in_smp;Linux 有一个全局变量, 包含了了所有的 IRQ : (kernel/irq/handle.c)struct irq_desc irq_descNR_IRQS _cacheline_aligned = 0 . NR_IRQS-1 = .status = IRQ_DISABLED, .chip = &no_irq_chip, .handle_irq = handle_bad_irq, .depth = 1,.lock = SPIN_LOCK_UNLOCK

5、ED, #ifdef CONFIG_SMP.affinity = CPU_MASK_ALL #endif3) irq_chip( 即在 genericirq 之前的 hw_interrupt_type) 以下这段是 genericirq 之前的:Linux 支持 N 种可编程中断控制器 PIC , 所以有一个 struct hw_interrupt_type ,对于 i8259A来说, 这个结构是 i8259A_irq_type , 对于 IOAPIC 来说, 根据设置为电平触发或边沿 触发的方式, 分别有 ioapic_level_type 和 ioapic_edge_type 两个不同的结

6、构。在引入 genericirq 补丁之后,定义了几个 irq_chip 结构:针对 i386 和 x86-64 各有一个定义的 : ioapic_chip, i8259A_chip, lapic_chip, msi_chip, ht_irq_chip, vmi_chip,针对 visw 体系的 :cobalt_irq_chip, piix4_master_irq_type, piix4_virtual_irq_type针对 voyager 体系的 :vic_chip其它目的的: no_irq_chip, dummy_irq_chip4) irq_statNR_CPUSLinux 定 义 了

7、一 个 全 局 的 数 组 , 用 来 描 述 每 个 CPU 上 的 irq 处 理 状 态 : (arch/i386/kernel/irq.c)DEFINE_PER_CPU(irq_cpustat_t, irq_stat) _cacheline_internodealigned_in_smp; EXPORT_PER_CPU_SYMBOL(irq_stat);irq_stat_t 的定义。typedef struct unsigned int _softirq_pending;unsigned long idle_timestamp;unsigned int _nmi_count; /* a

8、rch dependent */unsigned int apic_timer_irqs; /* arch dependent */ cacheline_aligned irq_cpustat_t;5) . 中断共享我们知道,多个中断源可以共享一个 irq 线。 Linux 的实现方式是,每个中断源都 有自己的一个 struct irqaction ,irqaction 结构的定义:struct irqaction irq_handler_t handler; unsigned long flags; cpumask_t mask; const char *name; void *dev_id

9、; struct irqaction *next; int irq; struct proc_dir_entry *dir;同一个 irq 可能有多个 irqaction ,组成一个链表。 struct irq_desc 中有个域:struct irqaction *action; /* IRQ action list */这个链表就包含了所有共享该 irq 号的中断源 (及其对应的 handler 等信息 )。 当 device driver进行request_irq()时,会为它生成一个irqaction,设置相应的值,然后挂载 irq_desc.action 队列中 (是添加在链表的最后

10、面 )。request_irq(irq, handler, irqflags, devname, dev_id) setup_irq(irq, irqaction)flags 有 3 个:IRQF_SHARED: 共享中断号IRQF_DISABLED: 就是旧时代的 SA_INTERRUPT ,设置了该标志, 则执行ISR 时关本地中断IRQF_SAMPLE_RANDOM: 告诉内核,本中断源可以用作随机数生成器的熵池只有满足以下条件, irq 才可以在多个中断源之间共享:a) . 每个中断源都愿意共享irq: request_irq 时指定了 IRQF_SHAREDb) .试图共享一个irq

11、的中断源,具有相同的触发机制(都是level trigger,或者都是edgetrigger) ,并且具有相同的 polarity( 都是低电平有效,或者都是高电平有效 )下面是set_irq()函数中判断old和new两个中断源是否可以share同一个irq号的代码:/* Cant share interrupts unless both agree to and are* the same type (level, edge, polarity). So both flag* fields must have IRQF_SHARED set and the bits which* set

12、the trigger type must match.*/if (!(old-flags & new-flags) & IRQF_SHARED) |(old-flags A new-flags) & IRQF_TRIGGER_MASK) old_name = old-name; goto mismatch;6) . 中断处理 (do_IRQ, _do_IRQ, generic_handle_irq, etc) - Part I: _do_IRQdo_IRQ() 是 genericirq 引入之前的通用中断处理函数(除了 IPI 中断,其它所有中断/异常用各个都经过它 ),它由 do_IRQ

13、调用,并调用 handle_IRQ_event( 而 handle_IRQ_event 会调driver 的 ISR) 。在引入 genericirq 之后, _do_IRQ() 函数已基本不用了。 64 位的 X86 系统上还可能使用/*/它 ( 通过 do_IRQ generic_handle_irq) , 32 位的 x86 已经完全不用它了。 然而我们还是看一下 _do_IRQ 函数,因为道理是一样的:_do_IRQ():/首先给 irq_descirq.lock 加锁,以免别的 CPU 访问该 desc 结构spin_lock(&desc-lock);/发送 ACK 给中断控制器if

14、 (desc-chip-ack)desc-chip-ack(irq);/* REPLAY is when Linux resends an IRQ that was dropped earlier* WAITING is used by probe to mark irqs that are being tested*/*清除 IRQ_REPLAY 和 IRQ_WAITING 标志 */status = desc-status & (IRQ_REPLAY | IRQ_WAITING);/* 设置 IRQ_PENDING 标志。 这个 flag 的意思是,已经 ACK 但尚未处理 */statu

15、s |= IRQ_PENDING; /* we _want_ to handle it */* If the IRQ is disabled for whatever reason, we cannot* use the action we have.*/* 如果 IRQ 被 disable 了,但是我们收到了中断,说明这是个 spurious interrupt ,* 有些有 BUG 的主板等硬件会干这种事*/action = NULL;/* 只要 IRQ_DISABLED 或者 IRQ_INPROGRESS 被设置,我们就不 handle 该 irq 。* 对于 IRQ_INPROGRESS 被设置的情况,说明此 irq 号的另一个实例正运行在* 另一个 CPU 上,我们就不处理了,而是让_那个 _ CPU 在运行完它的 ISR 时再检*/if (likely(!(status & (IRQ_

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 商业/管理/HR > 商业计划书

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号