欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 家装 > 中断管理常用API详解(二)

中断管理常用API详解(二)

2025/5/12 4:47:36 来源:https://blog.csdn.net/m0_74186706/article/details/146690535  浏览:    关键词:中断管理常用API详解(二)

一、__tasklet_hi_schedule(...)

        该函数的主要功能是将软中断具有比较高的优先级的任务优先调度处理。具体Linux内核源码设计如下:

        参数t:表示软中断的描述符添加到tasklet_hi_vec的尾部,获取CPU资源,被调度执行。 

调度优先级

  • __tasklet_schedule:调度的是普通优先级的 tasklet 。普通优先级的 tasklet 会在高优先级 tasklet 处理完之后,才会被内核调度执行 。当系统产生软中断时,普通 tasklet 不是最先被处理的对象 。
  • __tasklet_hi_schedule:用于调度高优先级的 tasklet 。在软中断处理过程中,高优先级的 tasklet 会优先于普通优先级的 tasklet 以及其他类型软中断(非高优先级软中断任务 )被处理。比如对于一些对响应时间要求苛刻的场景,像音频数据填充等低延迟需求的任务,就适合用 __tasklet_hi_schedule 来调度,以保证其能尽快执行。

所操作的队列

  • __tasklet_schedule:将 tasklet_struct 结构体(代表一个 tasklet 任务 )添加到 tasklet_vec 队列中。tasklet_vec 是每个 CPU 都有的一个用于存储普通优先级 tasklet 的队列 。
  • __tasklet_hi_schedule:把 tasklet_struct 结构体添加到 tasklet_hi_vec 队列 。tasklet_hi_vec 同样是每个 CPU 对应的队列,专门用来存放高优先级的 tasklet 。

触发的软中断类型

  • __tasklet_schedule:触发的是 TASKLET_SOFTIRQ 类型的软中断 。内核在处理软中断时,会根据软中断类型找到对应的处理逻辑,对于 TASKLET_SOFTIRQ 软中断,后续会执行 tasklet_vec 队列中注册的普通 tasklet 处理函数 。
  • __tasklet_hi_schedule:触发的是 HI_SOFTIRQ 类型的软中断 。当内核处理 HI_SOFTIRQ 软中断时,会去执行 tasklet_hi_vec 队列里的高优先级 tasklet 处理函数 。

 

【代码案例】

tasklethischedule.c

#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/delay.h>static struct tasklet_struct tl1, tl2;
static unsigned long data = 0;static void irqtasklet_actionfunc1(unsigned long data) {printk("调用自定义中断处理函数:irqtasklet_actionfunc1(...)函数.\n");printk("data1 : %ld\n", data);printk("打印输出irqtasklet_actionfunc1(...)函数里面的tasklet成员state的值为:%ld\n", (&tl1)->state);printk("退出自定义中断处理函数:irqtasklet_actionfunc1(...)函数.\n");
}static void irqtasklet_actionfunc2(unsigned long data) {printk("调用自定义中断处理函数:irqtasklet_actionfunc2(...)函数.\n");printk("data2 : %ld\n", data);printk("打印输出irqtasklet_actionfunc2(...)函数里面的tasklet成员state的值为:%ld\n", (&tl2)->state);printk("退出自定义中断处理函数:irqtasklet_actionfunc2(...)函数.\n");
}static int __init tasklethischedule_initfunc(void) {printk("调用内核初始化函数:tasklethischedule_initfunc(...)函数.\n");tasklet_init(&tl1, irqtasklet_actionfunc1, data);tasklet_init(&tl2, irqtasklet_actionfunc2, data);printk("打印输出内核模块初始化函数:tasklet的state成员值为:%ld\n", (&tl1)->state);printk("打印输出内核模块初始化函数:tasklet的state成员值为:%ld\n", (&tl2)->state);tasklet_schedule(&tl1);if(!test_and_set_bit(TASKLET_STATE_SCHED,&tl2.state)) // 测试并且设置中断状态__tasklet_hi_schedule(&tl2); // 将中断加入高优先级队列mdelay(10); // 等待执行printk("退出内核初始化函数:tasklethischedule_initfunc(...)函数.\n");return 0;
}static void __exit tasklethischedule_exitfunc(void) {tasklet_kill(&tl2); // 自动等待高优先级 tasklet 执行完毕tasklet_kill(&tl1); // 自动等待普通优先级 tasklet 执行完毕printk("内核正常退出:__tasklet_hi_schedule(...)函数.\n");
}MODULE_LICENSE("GPL");
module_init(tasklethischedule_initfunc);
module_exit(tasklethischedule_exitfunc);

Makefile

#!/bin/bashccflags_y += -O2ifneq ($(KERNELRELEASE),)
obj-m := tasklethischedule.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)default:$(MAKE) -C $(KERNELDIR) M=$(PWD) modules 
endifclean:rm -rf *.o *.ko *.mod.cdepend .depend dep:$(CC)  -M *.c > .depend 

编译插入卸载

 

二、tasklet_kill(...)

        该函数主要功能是阻塞当前线程,等待中断处理执行完毕。中断函数处理完毕state清0.具体内核源码设计如下:

tasklet特性:

  • 可以指定优先级;
  • 反复启用、禁用,在多次禁用之后必须先启用才能作用;
  • tasklet 可以嵌套,也就是它可以注册自己。

 【代码案例】

taskletkill.c

#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>static unsigned long data=0;
static struct tasklet_struct tl;static void irqtasklet_actionfunc(unsigned long data){printk("调用自定义中断函数:irqtasklet_actionfunc(...)函数.\n");printk("data : %ld\n",data);printk("输出irqtasklet_actionfunc(...)函数tasklet的state成员值为:%ld\n",(&tl)->state);printk("退出自定义中断函数:irqtasklet_actionfunc(...)函数.\n");
}static int __init taskletkill_initfunc(void){printk("调用内核模块函数:taskletkill_initfunc(...)函数.\n");tasklet_init(&tl,irqtasklet_actionfunc,data);printk("输出taskletkill_initfunc(...)函数tasklet的state成员值为:%ld\n",(&tl)->state);tasklet_schedule(&tl); // 将中断变量加入到软中断执行队列printk("输出taskletkill_initfunc(...)函数tasklet调用tasklet_schedule函数之后的state成员值为:%ld\n",(&tl)->state);tasklet_kill(&tl);printk("打印输出当前中断状态state成员值为:%ld\n",(&tl)->state);printk("退出内核模块函数:taskletkill_initfunc(...)函数.\n");return 0;
}static void __exit taskletkill_exitfunc(void){printk("正常退出内核:tasklet_kill(...)函数.\n");
}MODULE_LICENSE("GPL");
module_init(taskletkill_initfunc);
module_exit(taskletkill_exitfunc);

Makefile

#!/bin/bashccflags_y += -O2ifneq ($(KERNELRELEASE),)
obj-m := taskletkill.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)default:$(MAKE) -C $(KERNELDIR) M=$(PWD) modules 
endifclean:rm -rf *.o *.ko *.mod.cdepend .depend dep:$(CC)  -M *.c > .depend 

编译插入卸载

 

https://github.com/0voice

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词