Linux内核 tasklet_hi_schedule()

函数:tasklet_hi_schedule( )

文件包含:

        #include<linux/interrupt.h>

函数定义:

在内核源码中的位置: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( )函数是一个内联函数,其调用了函数__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对应的代码断已经被添加到向量链表中,无法再次添加,函数将不进行任何操作而返回。

通过此函数添加的软中断具有较高的优先级,会被优先响应处理。

输入参数说明:

此函数的输入参数是struct tasklet_struct结构体类型的变量,保存一个软中断的描述符信息,其定义及详细解释参看函数__tasklet_hi_schedule( )分析文档的输入参数说明部分。

返回参数说明:

此函数的返回值是void类型的变量,即此函数不返回任何值。

实例解析:

编写测试文件: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所示的结果。

Linux内核 tasklet_hi_schedule()

将函数tasklet_hi_schedule( )替换成函数tasklet_schedule( ),保存文件,重新编译模块,执行命令insmod tasklet_hi_schedule.ko插入内核模块,然后输入命令dmesg -c查看内核输出信息,出现如图B所示的信息。

Linux内核 tasklet_hi_schedule()

结果分析:

由图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( )注册的软中断具有较高的优先级,能先被调度处理。

酷客网相关文章:

赞(0)

评论 抢沙发

评论前必须登录!