• 软中断


    linux中断的处理分为顶半部和低半部,顶半部在硬件中断处理函数中实现(request_irq()中可申请用户回调函数),底半部的实现机制有三种:软中断/tasklet/workqueue。

    软中断的执行时机通常是顶半部返回的时候,tasklet是基于软中断实现的,因此也运行于软中断上下文。

    在linux内核中,用softirq_action结构体表征一个软中断,这个结构体包含软中断处理函数指针和传递给该函数的参数。使用open_softirq()函数可以注册软中断对应的处理函数,而raise_softirq()函数可以触发一个软中断。

    local_bh_disable()和local_bh_enable()是内核中用于禁止和使能软中断及tasklet底半部机制的函数。

    本文档描述基于3.14.77内核。

    1. 定义

    softirq定义在linux/interrupt.h中,实现在kernel/softirq.c中。tasklet是基于软中断实现的,相关代码也在这两个文件中。

    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,    /* Preferable RCU should always be the last softirq */
    
        NR_SOFTIRQS
    };
    
    #define SOFTIRQ_STOP_IDLE_MASK (~(1 << RCU_SOFTIRQ))
    
    /* map softirq index to softirq name. update 'softirq_to_name' in
     * kernel/softirq.c when adding a new softirq.
     */
    extern const char * const softirq_to_name[NR_SOFTIRQS];
    
    /* softirq mask and active fields moved to irq_cpustat_t in
     * asm/hardirq.h to get better cache usage.  KAO
     */
    
    struct softirq_action
    {
        void    (*action)(struct softirq_action *);
    };

    说明:之前linux版本,struct softirq_action包含两项action(软中断服务程序)和data(服务程序输入参数),因为其参数为softirq_action,可定义为全局变量而省去data定义。

    static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp;

    softirq相关函数

    asmlinkage void do_softirq(void);
    asmlinkage void __do_softirq(void);
    
    #ifdef __ARCH_HAS_DO_SOFTIRQ
    void do_softirq_own_stack(void);
    #else
    static inline void do_softirq_own_stack(void)
    {
        __do_softirq();
    }
    #endif
    
    extern void open_softirq(int nr, void (*action)(struct softirq_action *));
    extern void softirq_init(void);
    extern void __raise_softirq_irqoff(unsigned int nr);
    
    extern void raise_softirq_irqoff(unsigned int nr);
    extern void raise_softirq(unsigned int nr);

     2. 实现机制

     软中断守护程序是软中断机制实现的核心,它的实现过程简单。通过查询软中断的状态来判断是否发生事件,当发生事件就会映射软中断向量表,调用执行注册的action()函数就可以了。从这一点分析可以看出,软中断的服务程序是daemon。在linux中软中断daemon线程函数为do_softirq()。

    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_own_stack();
    
        local_irq_restore(flags);
    }

     网络软中断举例:

    当网络上有数据时,发生了硬件中断,硬件中断服务程序会接收网络数据,设置中断状态,并将网络数据挂接到链表中,进行中断调度,这一步可以通过net_schedule()函数完成。硬件中断服务程序最后退出并且CPU开始调度软中断,软中断daemon会发现网络软中断发生了事件,其会执行网络中断对应的服务程序,即进入网络协议栈处理程序。

    参考:

    1. linux中断编程

    2. linux内核对中断的处理方式

    3. 设备驱动开发详解 宋宝华

    4. linux网络编程 宋敬彬

  • 相关阅读:
    54.施工方案第二季(最小生成树)
    53.FIB词链
    52.1076 排序
    最短路径:我的理解--SPFA算法
    POJ2187Beauty Contest
    CodeForces 279B Books
    SDUT 2527 斗地主
    HDU1020 Encoding
    POJ 2635 The Embarrassed Cryptographer
    POJ 1942 Paths on a Grid(组合数)
  • 原文地址:https://www.cnblogs.com/twodog/p/12136686.html
Copyright © 2020-2023  润新知