Linux中与中断相关的内核数据结构

news/2024/7/24 5:04:30 标签: linux, 数据结构, java

【摘要】本文树妖详细讲解了Linux中与中断相关的内核数据结构及其内部联系。

八、中断相关的数据结构

8.1 irq_desc

  • 用于表示IRQ描述符的结构定义如下:\linux-2.6.32.63\include\linux\irq.h
struct irq_desc 
{
    unsigned int        irq;	//中断号
    unsigned int        *kstat_irqs;	//2. irq stats per cpu
#ifdef CONFIG_INTR_REMAP
    struct irq_2_iommu  *irq_2_iommu;    //3. iommu with this irq
#endif
    //4. highlevel irq-events handler [if NULL, __do_IRQ()]
    irq_flow_handler_t    handle_irq;

    //5. low level interrupt hardware access
    struct irq_chip        *chip;

    //6. MSI descriptor
    struct msi_desc        *msi_desc;

    //7. per-IRQ data for the irq_chip methods
    void            *handler_data;

    //8. platform-specific per-chip private data for the chip methods, to allow shared chip implementations
    void            *chip_data;

    /* IRQ action list */
    //9. the irq action chain
    struct irqaction    *action;    

    /* IRQ status */
    //10. status information
    unsigned int        status;        

    /* nested irq disables */
    //11. disable-depth, for nested irq_disable() calls
    unsigned int        depth;        

    /* nested wake enables */
    //12. enable depth, for multiple set_irq_wake() callers
    unsigned int        wake_depth;    

    /* For detecting broken IRQs */
    //13. stats field to detect stalled irqs
    unsigned int        irq_count;    

    /* Aging timer for unhandled count */
    //14. aging timer for unhandled count
    unsigned long        last_unhandled;    

    //15. stats field for spurious unhandled interrupts
    unsigned int        irqs_unhandled;

    //16. locking for SMP
    spinlock_t        lock;
#ifdef CONFIG_SMP
    //17. IRQ affinity on SMP
    cpumask_var_t        affinity;

    //18. node index useful for balancing
    unsigned int        node;
#ifdef CONFIG_GENERIC_PENDING_IRQ
    //19. pending rebalanced interrupts
    cpumask_var_t        pending_mask;
#endif
#endif
    //20. number of irqaction threads currently running
    atomic_t        threads_active;

    //21. wait queue for sync_irq to wait for threaded handlers
    wait_queue_head_t       wait_for_threads;
#ifdef CONFIG_PROC_FS
    //22. /proc/irq/ procfs entry
    struct proc_dir_entry    *dir;
#endif
    //23. flow handler name for /proc/interrupts output
    const char        *name;
} ____cacheline_internodealigned_in_smp;
  • status描述了IRQ的当前状态,irq.h中定义了各种表示当前状态的常数,可用于描述IRQ电路当前的状态。每个常数表示位串中的一个置位的标志位(可以同时设置)
/*
 * IRQ line status.
 *
 * Bits 0-7 are reserved for the IRQF_* bits in linux/interrupt.h
 *
 * IRQ types
 */
#define IRQ_TYPE_NONE        0x00000000    /* Default, unspecified type */
#define IRQ_TYPE_EDGE_RISING    0x00000001    /* Edge rising type */
#define IRQ_TYPE_EDGE_FALLING    0x00000002    /* Edge falling type */
#define IRQ_TYPE_EDGE_BOTH (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)
#define IRQ_TYPE_LEVEL_HIGH    0x00000004    /* Level high type */
#define IRQ_TYPE_LEVEL_LOW    0x00000008    /* Level low type */
#define IRQ_TYPE_SENSE_MASK    0x0000000f    /* Mask of the above */
#define IRQ_TYPE_PROBE        0x00000010    /* Probing in progress */

/* 
IRQ handler active - do not enter! 
与IRQ_DISABLED类似,IRQ_INPROGRESS会阻止其余的内核代码执行该处理程序
*/
#define IRQ_INPROGRESS        0x00000100    

/* 
IRQ disabled - do not enter!  
用户表示被设备驱动程序禁用的IRQ电路,标志通知内核不要进入处理程序
*/
#define IRQ_DISABLED        0x00000200    

/* 
IRQ pending - replay on enable 
当CPU产生一个中断但尚未执行对应的处理程序时,IRQ_PENDING标志位置位
*/
#define IRQ_PENDING        0x00000400    

/* 
IRQ has been replayed but not acked yet 
IRQ_REPLAY意味着该IRQ已经禁用,但此前尚有一个未确认的中断
*/
#define IRQ_REPLAY        0x00000800    
#define IRQ_AUTODETECT    0x00001000    /* IRQ is being autodetected */
#define IRQ_WAITING       0x00002000    /* IRQ not yet seen - for autodetection */

/* 
IRQ level triggered 
用于Alpha和PowerPC系统,用于区分电平触发和边沿触发的IRQ
*/
#define IRQ_LEVEL        0x00004000    

/* 
IRQ masked - shouldn't be seen again 
为正确处理发生在中断处理期间的中断,需要IRQ_MASKED标志位
*/
#define IRQ_MASKED        0x00008000    

/* 
IRQ is per CPU 
某个IRQ只能发生在一个CPU上时,将设置IRQ_PER_CPU标志位,在SMP系统中,该标志使几个用于防止并发访问的保护机制变得多余
*/
#define IRQ_PER_CPU        0x00010000    
#define IRQ_NOPROBE        0x00020000    /* IRQ is not valid for probing */
#define IRQ_NOREQUEST      0x00040000    /* IRQ cannot be requested */
#define IRQ_NOAUTOEN       0x00080000    /* IRQ will not be enabled on request irq */
#define IRQ_WAKEUP         0x00100000    /* IRQ triggers system wakeup */
#define IRQ_MOVE_PENDING   0x00200000    /* need to re-target IRQ destination */
#define IRQ_NO_BALANCING   0x00400000    /* IRQ is excluded from balancing */
#define IRQ_SPURIOUS_DISABLED    0x00800000    /* IRQ was disabled by the spurious trap */
#define IRQ_MOVE_PCNTXT    0x01000000    /* IRQ migration from process context */
#define IRQ_AFFINITY_SET   0x02000000    /* IRQ affinity was set from userspace*/
#define IRQ_SUSPENDED      0x04000000    /* IRQ has gone through suspend sequence */
#define IRQ_ONESHOT        0x08000000    /* IRQ is not unmasked after hardirq */
#define IRQ_NESTED_THREAD  0x10000000    /* IRQ is nested into another, no own handler thread */

#ifdef CONFIG_IRQ_PER_CPU
	#define CHECK_IRQ_PER_CPU(var) ((var) & IRQ_PER_CPU)
	#define IRQ_NO_BALANCING_MASK    (IRQ_PER_CPU | IRQ_NO_BALANCING)
#else
	#define CHECK_IRQ_PER_CPU(var) 0
	#define IRQ_NO_BALANCING_MASK    IRQ_NO_BALANCING
#endif

8.2 irq_chip

struct irq_chip 
{
    /*
    1. name for /proc/interrupts
    包含一个短的字符串,用于标识硬件控制器
        1) IA-32: XTPIC
        2) AMD64: IO-APIC
    */
    const char    *name;

    //2. start up the interrupt (defaults to ->enable if NULL),用于第一次初始化一个IRQ,startup实际上就是将工作转给enable
    unsigned int    (*startup)(unsigned int irq);

    //3. shut down the interrupt (defaults to ->disable if NULL)
    void        (*shutdown)(unsigned int irq);

    //4. enable the interrupt (defaults to chip->unmask if NULL)
    void        (*enable)(unsigned int irq);

    //5. disable the interrupt (defaults to chip->mask if NULL)
    void        (*disable)(unsigned int irq);

    //6. start of a new interrupt
    void        (*ack)(unsigned int irq);

    //7. mask an interrupt source
    void        (*mask)(unsigned int irq);

    //8. ack and mask an interrupt source
    void        (*mask_ack)(unsigned int irq);

    //9. unmask an interrupt source
    void        (*unmask)(unsigned int irq);

    //10. end of interrupt - chip level
    void        (*eoi)(unsigned int irq);

    //11. end of interrupt - flow level
    void        (*end)(unsigned int irq);

    //12. set the CPU affinity on SMP machines
    int        (*set_affinity)(unsigned int irq, const struct cpumask *dest);

    //13. resend an IRQ to the CPU
    int        (*retrigger)(unsigned int irq);

    //14. set the flow type (IRQ_TYPE_LEVEL/etc.) of an IRQ
    int        (*set_type)(unsigned int irq, unsigned int flow_type);

    //15. enable/disable power-management wake-on of an IRQ
    int        (*set_wake)(unsigned int irq, unsigned int on);

    //16. function to lock access to slow bus (i2c) chips
    void        (*bus_lock)(unsigned int irq);

    //17. function to sync and unlock slow bus (i2c) chips
    void        (*bus_sync_unlock)(unsigned int irq);

    /* Currently used only by UML, might disappear one day.*/
#ifdef CONFIG_IRQ_RELEASE_METHOD
    //18. release function solely used by UML
    void        (*release)(unsigned int irq, void *dev_id);
#endif
    /*
     * For compatibility, ->typename is copied into ->name.
     * Will disappear.
     */
    //19. obsoleted by name, kept as migration helper
    const char    *typename;
};
  • 该结构需要考虑内核中出现的各个IRQ实现的所有特性。因此,一个该结构的特定实例,通常只定义所有可能方法的一个子集,下面以IO-APIC、i8259A标准中断控制器作为例子:

    • \linux-2.6.32.63\arch\x86\kernel\io_apic.c

      static struct irq_chip ioapic_chip __read_mostly = {
          .name        = "IO-APIC",
          .startup    = startup_ioapic_irq,
          .mask        = mask_IO_APIC_irq,
          .unmask        = unmask_IO_APIC_irq,
          .ack        = ack_apic_edge,
          .eoi        = ack_apic_level,
      #ifdef CONFIG_SMP
          .set_affinity    = set_ioapic_affinity_irq,
      #endif
          .retrigger    = ioapic_retrigger_irq,
      };
      
    • \linux-2.6.32.63\arch\alpha\kernel\irq_i8259.c

      struct irq_chip i8259a_irq_type = {
          .name        = "XT-PIC",
          .startup    = i8259a_startup_irq,
          .shutdown    = i8259a_disable_irq,
          .enable        = i8259a_enable_irq,
          .disable    = i8259a_disable_irq,
          .ack        = i8259a_mask_and_ack_irq,
          .end        = i8259a_end_irq,
      };
      
  • 可以看到,运行该设备,只需要定义所有可能处理程序函数的一个子集

8.3 irqaction

  • struct irqaction结构是struct irq_desc中和IRQ处理函数相关的成员结构
struct irqaction 
{
    //1. name、dev_id唯一地标识一个中断处理程序
    irq_handler_t           handler;
    void                    *dev_id;

    void __percpu           *percpu_dev_id;

    //2. next用于实现共享的IRQ处理程序
    struct irqaction        *next;
    irq_handler_t           thread_fn;
    struct task_struct      *thread;
    unsigned int            irq;

    //3. flags是一个标志变量,通过位图描述了IRQ(和相关的中断)的一些特性,位图中的各个标志位可以通过预定义的常数访问
    unsigned int            flags;
    unsigned long           thread_flags;
    unsigned long           thread_mask;

    //4. name是一个短字符串,用于标识设备
    const char              *name;
    struct proc_dir_entry   *dir;
} ____cacheline_internodealigned_in_smp;
  • 几个irqaction实例聚集到一个链表中,链表的所有元素都必须处理同一个IRQ编号,在发生一个共享中断时,内核扫描该链表找出中断实际上的来源设备

image-20230505233103971


http://www.niftyadmin.cn/n/376440.html

相关文章

一起学SF框架系列4.5-模块context-AbstractRefreshableApplicationContext

AbstractRefreshableApplicationContext继承于AbstractApplicationContext,主要实现BeanFactory刷新(含初始化)。 类作用 1、在基类AbstractApplicationContext多次调用refresh()时,本类负责每次都创建一个新的内部 bean 工厂实…

34 KVM管理设备-管理虚拟磁盘

文章目录 34 KVM管理设备-管理虚拟磁盘34.1 概述34.2 操作步骤 34 KVM管理设备-管理虚拟磁盘 34.1 概述 虚拟磁盘类型主要包含virtio-blk、virtio-scsi、vhost-scsi等。virtio-blk模拟的是一种block设备,virtio-scsi和vhost-scsi模拟的是一种scsi设备。 virtio-b…

WebStorm 利用 FileWatchers 实现 JS、CSS 压缩

WebStorm 利用 FileWatchers 实现 JS、CSS 压缩 合理的使用 JS、CSS 压缩可以大大缩减文件的大小,使网页加载速度更快一些(虽然对我来说意义不大,因为我不做前端。。。)。 为什么会有这篇文章,是因为在做一些 JS 逆向…

IntersectionObserver实现无线滚动和懒加载

最近发现一个有意思的Web API IntersectionObserver 和大家分享一下 IntersectionObserver 可以用于检测元素是否进入视口,可以用于实现无限滚动、懒加载等功能。 使用场景:在Web应用中,可能需要实现无限滚动、懒加载等功能,使用…

NodeJs内存快照分析

(头等人,有本事,没脾气;二等人,有本事,有脾气;末等人,没本事,大脾气。——南怀瑾) NodeJs内存分析的必要性 回顾过去,我们排查web应用问题的途径…

Java基础 流程控制语句

顺序结构 顺序结构就是程序从上到下逐行地执行。表达式语句都是顺序执行的。并且上一 行对某个变量的修改对下一行会产生影响。 public class StatementTest{public static void main(String[] args){int x 1;int y 2; System.out.println("x " x);System.out.p…

RSA加密 多线程读写不安全

转自:(一场开源 RSA 库引发的“血案”) 导读 RSA 加密算法是一种非对称加密算法,该算法极为可靠,在现有技术条件下,很难破解,因此在软件开发中被广泛使用。你不必担心,本文不会介绍…

Docker进阶:容器网络、存储,安全和监控以及实践项目

✅作者简介:热爱Java后端开发的一名学习者,大家可以跟我一起讨论各种问题喔。 🍎个人主页:Hhzzy99 🍊个人信条:坚持就是胜利! 💞当前专栏:文章 🥭本文内容&am…