tasklet_hi_schedule函数功能描述:tasklet_hi_schedule( )函数是一个内联函数,其调用了函数__tasklet_hi_schedule( ),完成检查当前软中断所处的状态,并改变其状态,使其处于被调度状态,然后将此tasklet对应的软中断描述符加入到向量链表tasklet_hi_vec的尾部,等待获得CPU资源,被调度执行。此函数在执行之前,有一个条件判断,只有传递的参数表示的软中断描述符没有被调度时,才能将其加入tasklet_hi_vec中断向量链表。
函数功能实现过程:首先通过检查tasklet_struct的state的字段bit[0]的值,并把其值设置为1,返回其原值的“非”,如果其原值为0,则返回1,函数将调用函数__tasklet_hi_schedule( ),把tasklet对应的软中断描述符加入到向量tasklet_hi_vec的尾部;如果其原值为1,则返回0,说明此tasklet对应的代码断已经被添加到向量链表中,无法再次添加,函数将不进行任何操作而返回。
通过此函数添加的软中断具有较高的优先级,会被优先响应处理。
tasklet_hi_schedule文件包含
#include<linux/interrupt.h>
tasklet_hi_schedule函数定义
在内核源码中的位置:linux-3.19.3/include/linux/interrupt.h
函数定义格式:
static inline void tasklet_hi_schedule(struct tasklet_struct *t)
{
if (! test_and_set_bit(TASKLET_STATE_SCHED, &t->state))
__tasklet_hi_schedule(t);
}
tasklet_hi_schedule输入参数说明
此函数的输入参数是struct tasklet_struct结构体类型的变量,保存一个软中断的描述符信息,其定义及详细解释参看函数__tasklet_hi_schedule( )分析文档的输入参数说明部分。
tasklet_hi_schedule返回参数说明
此函数的返回值是void类型的变量,即此函数不返回任何值。
tasklet_hi_schedule实例解析
编写测试文件:tasklet_hi_schedule.c
头文件引用及全局变量定义:
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/init.h>
MODULE_LICENSE(“GPL”);
static unsigned long data=0;
static struct tasklet_struct tasklet, tasklet1;
中断处理函数定义:
// 自定义软中断处理函数,在此只是显示的作用
static void irq_tasklet_action(unsigned long data)
{
/*显示当前中断的状态*/
printk("in irq_tasklet_action the state of the tasklet is :%ld\n", (&tasklet)->state);
printk("tasklet running. by author\n");
return;
}
// 自定义软中断处理函数,在此只是显示的作用
static void irq_tasklet_action1(unsigned long data)
{
/*显示当前中断的状态*/
printk("in irq_tasklet_action1 the state of the tasklet1 is :%ld\n", (&tasklet1)->state);
printk("tasklet1 running. by author\n");
return;
}
模块初始化函数定义,验证函数的调用:
static int __init tasklet_hi_schedule_init(void)
{
printk("into tasklet_hi_schedule\n");
/*申请两个软中断*/
tasklet_init(&tasklet, irq_tasklet_action, data);
tasklet_init(&tasklet1, irq_tasklet_action1, data);
/*显示当前中断的状态*/
printk("The state of the tasklet is :%ld\n", (&tasklet)->state);
printk("The state of the tasklet1 is :%ld\n", (&tasklet1)->state);
tasklet_schedule(&tasklet); //把中断送入普通中断队列
tasklet_hi_schedule(&tasklet1); //调用函数tasklet_hi_schedule( )把中断送入高优先级队列
// tasklet_schedule(&tasklet1);
/*显示函数调用之后当前中断的状态*/
printk("The state of the tasklet is :%ld\n", (&tasklet)->state);
printk("The state of the tasklet1 is :%ld\n", (&tasklet1)->state);
tasklet_kill(&tasklet); //等待软中断处理函数的执行结束
tasklet_kill(&tasklet1);
printk("out tasklet_hi_schedule\n");
return 0;
}
模块退出函数定义:
static void __exit tasklet_hi_schedule_exit(void)
{
printk("Goodbye tasklet_hi_schedule\n");
return;
}
模块加载、退出函数调用:
module_init(tasklet_hi_schedule_init);
module_exit(tasklet_hi_schedule_exit);
实例结果及分析:
编译模块,执行命令insmod tasklet_hi_schedule.ko加载模块,然后输入命令dmesg -c查看内核输出信息,出现如图A
所示的结果。
将函数tasklet_hi_schedule( )替换成函数tasklet_schedule( ),保存文件,重新编译模块,执行命令insmod tasklet_hi_schedule.ko插入内核模块,然后输入命令dmesg -c查看内核输出信息,出现如图B
所示的信息。
结果分析:
由图A
可以看出函数tasklet_hi_schedule( )和函数tasklet_schedule( )执行之后,对应的软中断的状态值都变为了1,说明函数调用之后state字段的bit[0]=1,说明此时软中断处于调度状态,即被加入调度链表。当中断处理函数被调度执行时,当前中断的状态值是2,可以判断当前state字段的bit[1]是1,而bit[1]=1也表示当前中断正在执行。对于state字段bit位的说明请读者参看函数__tasklet_hi_schedule( )分析文档的输入参数说明部分。
图A
和图B
的唯一区别是两个中断处理函数被调度执行的顺序不同,在图A
中经过函数tasklet_hi_schedule( )处理的软中断,其先被调度执行,这种情况不是偶然,也非必然,但是大部分情况都是图A
出现的情况。函数tasklet_hi_schedule( )注册的软中断具有较高的优先级,能先被调度处理。