Linux内核中的软中断、tasklet

  • 上半部指的是中断处理程序,下半部则指的是一些虽然与中断有相关性但是可以延后执行的任务。

  • 在网络传输中,网卡接收到数据包这个事件不一定需要马上被处理,适合用下半部去实现;但是用户敲击键盘这样的事件就必须马上被响应,应该用中断实现。

  • 中断不能被相同类型的中断打断,而下半部依然可以被中断打断;中断对于时间非常敏感,而下半部基本上都是一些可以延迟的工作。由于二者的这种区别,所以对于一个工作是放在上半部还是放在下半部去执行,可以参考下面4条:

    • 如果一个任务对时间非常敏感,将其放在中断处理程序中执行。

    • 如果一个任务和硬件相关,将其放在中断处理程序中执行。

    • 如果一个任务要保证不被其他中断(特别是相同的中断)打断,将其放在中断处理程序中执行

    • 其他所有任务,考虑放在下半部去执行。

在这里插入图片描述

  • 软中断

  • 软中断作为下半部机制的代表,是随着SMP(share memory processor)的出现应运而生的,它也是tasklet实现的基础(tasklet实际上只是在软中断的基础上添加了一定的机制)

  • 软中断一般是“可延迟函数”的总称,它的出现就是因为要满足上面所提出的上半部和下半部的区别,使得对时间不敏感的任务延后执行,而且可以在多个CPU上并行执行,使得总的系统效率可以更高。它的特性包括:

    • 产生后并不是马上可以执行,必须要等待内核的调度才能执行。软中断不能被自己打断(即单个cpu上软中断不能嵌套执行),只能被硬件中断打断(上半部)。

    • 可以并发运行在多个CPU上(即使同一类型的也可以)。所以软中断必须设计为可重入的函数(允许多个CPU同时操作),因此也需要使用自旋锁来保其数据结构。

  • 相关数据结构

  • 软中段描述符 struct softirq_action{ void (action)(struct softirq_action);};

  • 描述每一种类型的软中断,其中void(*action)是软中断触发时的执行函数。

    软中断全局数据和类型
    在这里插入图片描述

  • 相关API

  • 注册软中断

  • *void open_softirq(int nr, void (*action)(struct softirq_action ))

  • 注册对应类型的处理函数到全局数组softirq_vec中。例如网络发包对应类型为NET_TX_SOFTIRQ的处理函数net_tx_action.

  • 触发软中断

  • void raise_softirq(unsigned int nr)

  • 以软中断类型nr作为偏移量置位每cpu变量irq_stat[cpu_id]的成员变量__softirq_pending,这也是同一类型软中断可以在多个cpu上并行运行的根本原因.

  • 软中断执行函数

  • do_softirq–>__do_softirq

  • 执行软中断处理函数__do_softirq前首先要满足两个条件:

    • 不在中断中(硬中断、软中断和NMI) 。

    • 有软中断处于pending状态。

  • 为了避免软件中断在中断嵌套中被调用,并且达到在单个CPU上软件中断不能被重入的目的。

  • 实现原理和实例

  • 软中断的调度时机:

    • do_irq完成I/O中断时调用irq_exit。

    • 系统使用I/O APIC,在处理完本地时钟中断时。

    • local_bh_enable,即开启本地软中断时。

    • SMP系统中,cpu处理完被CALL_FUNCTION_VECTOR处理器间中断所触发的函数时。

    • ksoftirqd/n线程被唤醒时。

  • 处理流程
    -在这里插入图片描述
    在这里插入图片描述

  • 首先调用local_softirq_pending函数取得目前有哪些位存在软件中断。

  • 调用__local_bh_disable关闭软中断,其实就是设置正在处理软件中断标记,在同一个CPU上使得不能重入__do_softirq函数。

  • 重新设置软中断标记为0,set_softirq_pending重新设置软中断标记为0,这样在之后重新开启中断之后硬件中断中又可以设置软件中断位。

  • 调用local_irq_enable,开启硬件中断。

  • 之后在一个循环中,遍历pending标志的每一位,如果这一位设置就会调用软件中断的处理函数。在这个过程中硬件中断是开启的,随时可以打断软件中断。这样保证硬件中断不会丢失。

  • 之后关闭硬件中断(local_irq_disable),查看是否又有软件中断处于pending状态,如果是,并且在本次调用__do_softirq函数过程中没有累计重复进入软件中断处理的次数超过max_restart=10次,就可以重新调用软件中断处理。如果超过了10次,就调用wakeup_softirqd()唤醒内核的一个进程来处理软件中断。设立10次的限制,也是为了避免影响系统响应时间。

  • 调用_local_bh_enable开启软中断。

  • tasklet

  • 由于软中断必须使用可重入函数,这就导致设计上的复杂度变高,作为设备驱动程序的开发者来说,增加了负担。而如果某种应用并不需要在多个CPU上并行执行,那么软中断其实是没有必要的。因此诞生了弥补以上两个要求的tasklet。它具有以下特性:

    • 一种特定类型的tasklet只能运行在一个CPU上,不能并行,只能串行执行。

    • 多个不同类型的tasklet可以并行在多个CPU上。

    • 软中断是静态分配的,在内核编译好之后,就不能改变。但tasklet就灵活许多,可以在运行时改变(比如添加模块时)。

  • tasklet是在两种软中断类型的基础上实现的,因此如果不需要软中断的并行特性,tasklet就是最好的选择。也就是说tasklet是软中断的一种特殊用法,即延迟情况下的串行执行。

  • 相关数据结构

  • tasklet描述符

    在这里插入图片描述

  • task链表
    在这里插入图片描述

  • 相关API

  • 定义tasklet

    在这里插入图片描述

  • tasklet操作

    • static inline void tasklet_disable(struct tasklet_struct *t)

      • //函数暂时禁止给定的tasklet被tasklet_schedule调度,直到这个tasklet被再次被enable;若这个tasklet当前在运行,这个函数忙等待直到这个tasklet退出
    • static inline void tasklet_enable(struct tasklet_struct *t)

      • //使能一个之前被disable的tasklet;若这个tasklet已经被调度,
        它会很快运行。tasklet_enable和tasklet_disable必须匹配调用, 因为内核跟踪每个tasklet的"禁止次数"
    • static inline void tasklet_schedule(struct tasklet_struct *t)

      • //调度 tasklet 执行,如果tasklet在运行中被调度, 它在完成后会再次运行;
        这保证了在其他事件被处理当中发生的事件受到应有的注意. 这个做法也允许一个 tasklet 重新调度它自己
    • tasklet_hi_schedule(struct tasklet_struct *t)

      • //和tasklet_schedule类似,只是在更高优先级执行。当软中断处理运行时, 它处理高优先级 tasklet
        在其他软中断之前,只有具有低响应周期要求的驱动才应使用这个函数, 可避免其他软件中断处理引入的附加周期.
    • tasklet_kill(struct tasklet_struct *t)

      • //确保了 tasklet 不会被再次调度来运行,通常当一个设备正被关闭或者模块卸载时被调用。如果 tasklet 正在运行,
        这个函数等待直到它执行完毕。若 tasklet 重新调度它自己,则必须阻止在调用 tasklet_kill 前它重新调度它自己,如同使用
        del_timer_sync
  • 实现原理

  • 调度原理

    在这里插入图片描述

  • tasklet执行过程

  • TASKLET_SOFTIRQ对应执行函数为tasklet_action,HI_SOFTIRQ为tasklet_hi_action,以tasklet_action为例说明,tasklet_hi_action大同小异。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值