baron · 3月27日 · 四川

Linux Kernel中断下半部分实现的三种方式

快速连接

👉👉👉【精选】ARMv8/ARMv9架构入门到精通-目录 👈👈👈


 title=

目前有三种中断的三种机制:

  • 软中断
  • tasklet
  • 工作队列

1、软中断

软中断是一组静态定义的下半部接口,有 32 个,可以在所有处理器上同时执行,类型相同也可以;在编译时静态注册。
软中断的相关函数:

  • 注册软中断 open_softirq
  • 触发软中断 raise_softirq
  • 执行软中断 do_softirq

Linux Kernel中定义的软中断:

(linux/include/linux/interrupt.h)

enum
{
    HI_SOFTIRQ=0,
    TIMER_SOFTIRQ,
    NET_TX_SOFTIRQ,
    NET_RX_SOFTIRQ,
    BLOCK_SOFTIRQ,
    IRQ_POLL_SOFTIRQ,
    TASKLET_SOFTIRQ,
    SCHED_SOFTIRQ,
    HRTIMER_SOFTIRQ,
    RCU_SOFTIRQ,    /* Preferable RCU should always be the last softirq */

    NR_SOFTIRQS
};

软中断执行函数如下:

(linux/kernel/softirq.c)

 asmlinkage __visible void do_softirq(void)
 {
     __u32 pending;
     unsigned long flags;
 
     if (in_interrupt())
         return;
 
     local_irq_save(flags);
 
     pending = local_softirq_pending();
 
     if (pending && !ksoftirqd_running(pending))
         do_softirq_own_stack();
 
     local_irq_restore(flags);
 }

代码一上来就判断是否在中断处理中,如果在立刻退出函数。这说明如果有其他软中断触发,则立即返回。所以,软中断不能被另外一个软中断抢占!唯一可以抢占软中断的是中断处理程序,所以软中断允许响应中断。虽然不能在本处理器上抢占,但是其他的软中断甚至同类型可以再其他处理器上同时执行。由于这点,所以对临界区需要加锁保护。

软中断给对时间要求最严格的下半部使用。目前只有网络,内核定时器和 tasklet 建立在软中断上。

2、tasklet

Tasklet是建立在软中断之上的下半部机制,tasklet和软中断很类似,但是tasklet的接口更简单,也不需要严格的锁机制。因为tasklet是使用软中断来实现的,所以tasklet本身就是软中断。

tasklet使用两种软中断来实现:HI_SOFTIRQ和TASKLET_SOFTIRQ。两者的唯一区别在于优先级,前者优先级更高,总是先于后者执行。

tasklet使用tasklet_struct结构来表示,每个结构体表示一个唯一的tasklet,定义在<linux/interrupt.h>中

(linux/include/linux/interrupt.h)

struct tasklet_struct
{
    struct tasklet_struct *next;
    unsigned long state;
    atomic_t count;
    bool use_callback;
    union {
        void (*func)(unsigned long data);
        void (*callback)(struct tasklet_struct *t);
    };
    unsigned long data;
};

Tasklet的使用:

(1)、声明一个新的tasklet

struct tasklet_struct my_tasklet = { NULL, 0, ATOMIC_INIT(0),  my_tasklet_handler, dev };

或者

tasklet_init(t, tasklet_handler, dev); /* dynamically as opposed to statically */

(2)、tasklet的处理程序

void tasklet_handler(unsigned long data)

注意:和软中断类似,tasklet不能睡眠(阻塞),因为软中断是运行在中断上下文中的,而tasklet是使用软中断来实现的。

(3)、tasklet的调度
使用tasklet_schedule()进行调度(类似软中断的触发),传入参数为指向tasklet_struct的指针。tasklet被调度后,内核会在合适的时机执行该taskelt。(详见前面的tasklet调度的实现)。如果一个tasklet在执行前被调度了多次,还是只会执行一次(tasklet链表中不会有重复的tasklet)。如果一个tasklet在运行中被调度了(比如被另一个处理器上执行的代码调度了),那么这个tasklet会被重新调度并在下次内核处理tasklet的时候再次执行。

3、工作队列

工作队列是和软中断或者tasklet不同的一种下半部机制。工作队列将工作推迟,交给内核线程执行(所以工作队列总是运行在进程上下文中)。工作队列的这种实现可以很好的利用进程上下文的优势,最重要的就是可以睡眠也可以被调度(抢占)。与之相反的是,软中断和tasklet是不能睡眠和被调度的。

可以自己创建工作队列,但是大部分驱动都会使用系统提供的缺省的工作队列类型events,该类型的工作队列的内核线程名字为 events/n,n为处理器编号,每个处理器对应一个内核线程。如果下半部的工作是处理器密集型并且对性能敏感的,可以考虑创建自己的内核线程。比如XFS文件系统就自己创建了两种内核线程。

工作队列的使用:--(缺省工作队列events)

(1)、创建工作(Creaing Work)

DECLARE_WORK(name, void (*func)(void *), void *data);  //静态
INIT_WORK(struct work_struct *work, void (*func)(void *), void *data);  //动态

(2)、定义工作队列处理函数

void work_handler(void *data)

(3)、对工作(work)进行调度

内核提供了两个函数对使用缺省工作队列events的工作进行调度

schedule_work(&work);
schedule_delayed_work(&work, delay);
  • schedule_work()会立刻对工作(work)进行调度,一旦其所在的处理器上的events内核线程被唤醒,该工作就会被执行。
  • schedule_delayed_work()会延后一定数量的(由dealy指定)的timer tick后再进行调度。

创建自己的内核线程工作队列

(1)、创建内核线程工作队列
如果需要利用单独的内核线程的(不用events的内核线程)的性能优势,可以通过函数struct workqueue_struct create_workqueue(const char name)创建一个新的工作队列,参数是工作队列的名字。比如缺省的events工作队列的创建:

struct workqueue_struct *keventd_wq;
keventd_wq = create_workqueue(“events”);

这个函数会创建所有的内核线程(每个处理器一个),并且做些准备好让这些内核线程可以处理工作

(2)、工作队列调度

int queue_work(struct workqueue_struct *wq, struct work_struct *work)
int queue_delayed_work(struct workqueue_struct *wq,
                        struct work_struct *work,
                        unsigned long delay)

总结

下半部上下文说明
软中断中断上下文不能睡眠、不能被抢占
tasklet中断上下文不能睡眠、不能抢占、同类型tasklet不能并行
工作队列进程上下文可以睡眠、可以被抢占

在这里插入图片描述
《ARMv8/ARMv9架构学习系列课程》全系列,共计51节课,超15h的视频课程


关注"Arm精选"公众号,备注进ARM交流讨论区。
图片1.png

推荐阅读
关注数
9437
内容数
191
以易懂、渐进、有序的方式,深入探讨ARMv8/ARMv9架构的核心概念。我们将从基础知识开始,逐步深入,覆盖最新的架构,不再纠缠于过时技术。本系列内容包含但不限于ARM基础、SOC芯片基础、Trustzone、gic、异常和中断、AMBA、Cache、MMU等内容,并将持续更新。
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息