中断管理常用API详解(三)
一、tasklet_disable_nosync(...)
该函数主要功能为增加tasklet_struct结构体变量中的count字段的值,此结构体描述的软中断不能被调度执行,使其处于睡眠状态。具体Linux内核源码设计如下:
【代码案例】
taskletdisablenosynctest.c
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
static struct tasklet_struct tl;
static unsigned long data = 0;
// 自定义中断处理函数
static void irqtask_actionfunc(unsigned long data){
printk("调用自定义中断处理函数:irqtask_actionfunc(...)函数.\n");
printk("data : %ld\n",data);
printk("打印输出:OK.\n");
printk("退出自定义中断处理函数:irqtask_actionfunc(...)函数.\n");
}
static int __init taskletdisablenosync_initfunc(void){
printk("调用内核模块函数:taskletdisablenosync_initfunc(...)函数.\n");
tasklet_init(&tl,irqtask_actionfunc,data);
tasklet_schedule(&tl); // 将软中断加入到等待队列,等待调度执行处理
printk("调用tasklet_disable_nosync(...)函数之前 count成员值为:%d\n", atomic_read(&tl.count));
tasklet_disable_nosync(&tl);
if(atomic_read(&tl.count) != 0) // 测试当前的count成员值
printk("tasklet is disable(禁用).\n");
printk("调用tasklet_disable_nosync(...)函数之后 count成员值为:%d\n", atomic_read(&tl.count));
tasklet_enable(&tl);
if(atomic_read(&tl.count) == 0)
printk("tasklet is enable(启用).\n");
printk("tasklet count成员值为:%d\n", atomic_read(&tl.count));
tasklet_kill(&tl); // 等待软中断的执行结束
printk("退出内核模块函数:taskletdisablenosync_initfunc(...)函数.\n");
return 0;
}
static void __exit taskletdisablenosync_exitfunc(void){
printk("正常退出内核:tasklet_disable_nosync(...)函数.\n");
}
MODULE_LICENSE("GPL");
module_init(taskletdisablenosync_initfunc);
module_exit(taskletdisablenosync_exitfunc);
Makefile
#!/bin/bash
ccflags_y += -O2
ifneq ($(KERNELRELEASE),)
obj-m := taskletdisablenosynctest.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
endif
clean:
rm -rf *.o *.ko *.mod.c
depend .depend dep:
$(CC) -M *.c > .depend
编译插入卸载
二、 tasklet_disable
该函数的主要功能是增加软中断描述符的count成员的值,让软中断处于睡眠状态(不能响应对应的中断)。具体Linux源码设计如下:
该函数会暂时禁止给定的tasklet被tasklet_schedule调度,知道这个tasklet被再次enable。若这个tasklet正在当前执行,这个函数忙等到这个tasklet退出。
tasklet_disable
- 当前正在运行的
tasklet
:当调用tasklet_disable
时,如果指定的tasklet
正在某个 CPU 上运行,该函数会进入忙等待状态,直到这个tasklet
执行完毕。它无法立即终止当前正在运行的tasklet
,只能等待其自然结束。- 后续
tasklet
的运行:在等待当前运行的tasklet
结束后,tasklet_disable
会将该tasklet
标记为禁用状态。此后,即使有其他事件触发该tasklet
调度,它也不会再被执行,直到调用tasklet_enable
重新启用它。
tasklet_disable_nosync
- 当前正在运行的
tasklet
:tasklet_disable_nosync
不会等待当前正在运行的tasklet
结束。也就是说,当调用该函数时,如果指定的tasklet
正在执行,它会继续执行完,tasklet_disable_nosync
不会进行任何等待操作。- 后续
tasklet
的运行:调用tasklet_disable_nosync
后,该tasklet
会被标记为禁用状态,后续不会再被调度执行,直到调用tasklet_enable
重新启用它。综上所述,这两个函数都不能直接禁止当前正在运行的
tasklet
,tasklet_disable
会等待当前运行的tasklet
结束后再禁用后续执行,而tasklet_disable_nosync
则直接禁用后续执行,不等待当前运行的tasklet
结束。
【代码案例】
taskletdisabletest.c
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
static struct tasklet_struct tl;
static unsigned long data = 0;
static void irqtasklet_actionfunc(unsigned long data){
printk("data : %ld\n",data);
printk("调用自定义中断函数:irqtasklet_actionfunc(...)函数.\n");
}
static int __init taskletdisalbe_initfunc(void){
tasklet_init(&tl,irqtasklet_actionfunc,data);
tasklet_schedule(&tl);
printk("调用内核模块函数:taskletdisalbe_initfunc(...)函数.\n");
printk("输出调用tasklet_disable之前的count成员的值为:%d\n",atomic_read(&tl.count));
tasklet_disable(&tl); // 调用此函数使tasklet对应的处理函数不能执行
if(atomic_read(&tl.count)!=0)
printk("tasklet is disabled.\n");
printk("输出调用tasklet_disable之后的count成员的值为:%d\n",atomic_read(&tl.count));
tasklet_enable(&tl); // 调用此函数使tasklet启用
if(atomic_read(&tl.count)==0)
printk("tasklet is enabled.\n");
printk("调用tasklet_enable函数之后tasklet的count成员值为:%d\n",atomic_read(&tl.count));
tasklet_kill(&tl);
printk("退出内核模块函数:taskletdisalbe_initfunc(...)函数.\n");
return 0;
}
static void __exit taskletdisalbe_exitfunc(void){
printk("正常退出内核:tasklet_disable(...)函数.\n");
}
MODULE_LICENSE("GPL");
module_init(taskletdisalbe_initfunc);
module_exit(taskletdisalbe_exitfunc);
Makefile
#!/bin/bash
ccflags_y += -O2
ifneq ($(KERNELRELEASE),)
obj-m := taskletdisabletest.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
endif
clean:
rm -rf *.o *.ko *.mod.c
depend .depend dep:
$(CC) -M *.c > .depend
编译插入卸载
https://github.com/0voice