Linux中断下半部tasklet

Linux中断下半部tasklet

tasklet是Linux内核中“可延迟执行”机制、或“中断下半部”的一种。tasklet的优先级别较低,而且中断处理过程中可以被打断。但被打断之后,还能进行自我恢复,断点续运行。

1.数据结构

struct tasklet_struct
{
    struct tasklet_struct *next;
    unsigned long state;
    atomic_t count;
    void (*func)(unsigned long);
    unsigned long data;
};

2.初始化

/* 静态 */

//可以直接用tasklet_schedule()调度
#define DECLARE_TASKLET(name, func, data) \
struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(0), func, data }

//需要使用tasklet_enable()使能,才可以被调度运行
#define DECLARE_TASKLET_DISABLED(name, func, data) \
struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(1), func, data }

/* 动态 */
extern void tasklet_init(struct tasklet_struct *t,void (*func)(unsigned long), unsigned long data);

3.调度tasklet

//将tasklet加入到调度链表里面,tasklet就能得到执行,每调用这个函数一次,tasklet只能执行一次,要再次执行需要重新调用这个函数
static inline void tasklet_schedule(struct tasklet_struct *t);

4.销毁tasklet

//设备关闭和模块卸载的时候,调用来杀死tasklet。如果当前tasklet在运行,会等待完成后,再杀死
extern void tasklet_kill(struct tasklet_struct *t);
extern void tasklet_kill_immediate(struct tasklet_struct *t, unsigned int cpu);

5.其他tasklet接口

static inline int tasklet_trylock(struct tasklet_struct *t)
static inline void tasklet_unlock(struct tasklet_struct *t)
static inline void tasklet_unlock_wait(struct tasklet_struct *t)

//比tasklet_schedule优先级更高,可以得到更快处理
static inline void tasklet_hi_schedule(struct tasklet_struct *t)
//和tasklet_hi_schedule差不多,只是更安全
static inline void tasklet_hi_schedule_first(struct tasklet_struct *t)
//和tasklet_disable一样,如果当前tasklet在运行,这个函数不会等待完成就先返回,当tasklet完成退出后,再禁止。 
static inline void tasklet_disable_nosync(struct tasklet_struct *t)
//禁止tasklet,即使tasklet_schedule已经把tasklet添加到调度链表里,也得不到执行,必须要用tasklet_enable使能才可以。如果当前tasklet正在运行,tasklet_disable会等待执行完,然后禁止,返回。 
static inline void tasklet_disable(struct tasklet_struct *t)
//使能tasklet,和tasklet_disable要成对使用    
static inline void tasklet_enable(struct tasklet_struct *t)
//和tasklet_enable一样
static inline void tasklet_hi_enable(struct tasklet_struct *t)

================================================================================================
struct tasklet_hrtimer {
    struct hrtimer      timer;
    struct tasklet_struct   tasklet;
    enum hrtimer_restart    (*function)(struct hrtimer *);
};

extern void
tasklet_hrtimer_init(struct tasklet_hrtimer *ttimer,enum hrtimer_restart (*function)(struct hrtimer *),clockid_t which_clock, enum hrtimer_mode mode);

static inline 
int tasklet_hrtimer_start(struct tasklet_hrtimer *ttimer, ktime_t time,const enum hrtimer_mode mode)

static inline void tasklet_hrtimer_cancel(struct tasklet_hrtimer *ttimer)

6.驱动实例

#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/jiffies.h>

static struct tasklet_struct test_tasklet;

static void function(unsigned long data)
{
    printk(KERN_INFO "=======before schedule:%ld, in running:%ld=======\n",data,jiffies);
}

static int __init tasklet_test_init(void)
{
    unsigned long tmp;
    tmp = jiffies;
    tasklet_init(&test_tasklet, function, tmp);
    tasklet_schedule(&test_tasklet);

    printk(KERN_ALERT "==============tasklet_test_init===============\n");
    return 0;
}

static void __exit tasklet_test_exit(void)
{
    printk(KERN_ALERT "==============tasklet_test_exit===============\n");
    tasklet_kill(&test_tasklet);
}

module_init(tasklet_test_init);
module_exit(tasklet_test_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR( "wyy");

猜你喜欢

转载自blog.csdn.net/wyy626562203/article/details/81290748