11 tasklet

代码

1 tasklet调度机制

task属于软中断,有HI_SOFTIRQ和TASKLET_SOFTIRQ两种类型。tasklet又名“小任务”,所以过于复杂的操作一般交给workqueue或其他机制实现

image

中断下半部softirq_init中会调用tasklet_hi_action或taskletaction。两者最终都会调用到tasklet_action_common

在while循环中遍历链表中每一个tasklet,如果tasklet没有执行,且count字段为0,则调用它的回调函数。否则将其插入清空后的链表

简单说就是被执行过的tasklet会从链表中删除,没有被执行过的tasklet会被重新放入一个被清空过后的链表

注意:tasklet无法从链表中删除函数,只能通过task_disable去阻止它执行。tasklet_kill并不删除tasklet,而是清除tasklet的状态

2 常用API和数据结构

函数和宏 描述
DECLARE_TASKLET/DECLARE_TASKLE_OLD 定义tasklet,count字段初始化为0
DECLARE_TASKLET_DISABLED/DECLARE_TASKLET_DISABLED_OLD 定义tasklet,count字段初始化为1
tasklet_init 初始化tasklet,count幅值为0
tasklet_enable 使能tasklet
tasklet_disable 禁止tasklet,如果tasklet正在执行,需要等待其执行完毕才会返回
tasklet_hi_schedule 调度tasklet执行,对应HI_SOFTIRQ
tasklet_schedule 调度tasklet执行,对应TASKLET_SOFTIRQ
tasklet_kill 清除tasklet调度和运行状态,如果tasklet正在执行,需要等待其执行完毕才会返回

2.1 tasklet_struct

struct tasklet_struct
{
	struct tasklet_struct *next;
	unsigned long state;			/* 当前状态. TASKLET_STATE_SCHED:加入调度等待执行。TASKLET_STATE_RUN:正在执行 */
	atomic_t count;					/* 此tasklet是否使能 */
	void (*func)(unsigned long);	/* 回调函数 */
	unsigned long data;				/* 回调函数的参数 */
};

state	: 表示tasklet的状态
		  bit0为tasklet是否放入了tasklet队列。(1为已经放入了tasklet队列)
		  bit1为此tasklet是否已经执行完毕。(0表示内核已经调度完成此小任务)
count	: 表示task是否使能。0表示使能

2.2 tasklet_init

/**
 * 初始化task_let,并使能
 */
void tasklet_init(struct tasklet_struct *t,
		  void (*func)(unsigned long), unsigned long data)
{
	t->next = NULL;
	t->state = 0;
	atomic_set(&t->count, 0);
	t->func = func;
	t->data = data;
}

2.3 tasklet_enable、tasklet_disable

/**
 * tasklet使能和禁止
 */
static inline void tasklet_enable(struct tasklet_struct *t);
static inline void tasklet_disable(struct tasklet_struct *t);

2.4 task_schedule

/**
 * 开始taskletd的调度,将tasklet放入tasklet的队列
 */
static inline void tasklet_schedule(struct tasklet_struct *t);

2.5 tasklet_kill

/**
 * 如何一个进程没有被调度(未被放入队列),择将它的调度状态变更为0
 * 如果一个tasklet已经被调度(已经放入队列),择将会等其被执行后再将其调度状态清0
 */
void tasklet_kill(struct tasklet_struct *t);
posted @ 2023-03-19 16:41  人民广场的二道贩子  阅读(31)  评论(0)    收藏  举报