①tasklet是基于软中断实现的,其优先级高于进程而低于硬件中断,同样不能做休眠操作。
②内核描述tasklet的数据结构
目前主要关注两个成员:func和data
func:指向的函数即为延后处理函数,形参unsigned long是要传递的参数
data:给延后处理函数传递的参数
③使用tasklet实现底半部编程的大体步骤总结
1)定义tasklet对象
struct tasklet_struct A; //定义tasklet对象
2)初始化tasklet对象,使用taskle_init函数
tasklet_init(&A, //初始化对象
A_function, //给tasklet对象指定一个延后处理函数
(unsigned long)&g_data //给延后处理函数传递的参数
);
3)根据需求编写延后处理函数(A_function)
void A_function(unsigned long data)
{
//data用来保存给延后处理函数传递的参数
//data=(unsigned long)&data
//使用时注意数据类型强转
......;
//该函数为底半部程序内容,应该做一些不紧急的
//耗时时间长的内容
}
4)使用过tasklet_schedule函数向内核注册添加tasklet对象,也就是说内核tasklet对象的延后处理函数一旦注册成功,内核就会在适当的时候调用延后处理函数
注:在有顶半部中断处理函数的情况下,一般都是在顶半部代码中进行注册,如果没有顶半部时,根据需求在适当代码处注册
tasklet_schedule(&A);
①工作队列诞生的原因就是解决tasklet的延后处理函数不能休眠的问题,这样可以在需要的场合在延后处理函数中进行休眠操作。
②工作队列基于进程实现,所以其延后处理函数可以进行休眠操作,但是优先级最低
③内核描述工作队列的数据结构
主要关注成员func:制定一个延后处理函数,此函数中可以进行休眠操作。
④使用工作队列实现底半部编程的大体步骤总结
1)定义工作队列对象
struct work_struct A;
2)使用INIT_WORK宏,初始化工作队列对象
INIT_WORK(&A,A_function);//添加一个延后处理函数
3)根据用户需求编写延后服务程序
void A_function(struct work_struct *work)
{
//work = &A;
//做不紧急,耗时较长的内容
}
4)使用schedule_work函数向内核注册延后服务程序
schedule_work(&A); //一旦登记完成,内核会在适当的时候执行延后处理函数
①软中断实现延后执行的特点
1)软中断对应的延后处理函数优先级高于进程低于硬件中断
2)软中断延后处理函数同样不能进行休眠操作
3)软中断延后处理函数同一时刻能够运行在多个CPU核上,"效率更高"
注:内核要求其延后处理函数必须具备可重入性,就是尽量不要访问全局变量,如果非要访问,必须要进行互斥保护,但这种互斥访问最终降低代码的执行效率
②tasklet基于软中断实现,但是其延后处理函数同一时刻只能运行在一个CPU核上,tasklet开发难度降低,它的出现就是替代软中断
③软中断的延后处理代码不能向tasklet和工作队列一样insmod和rmmod,只能和uImage编译在一起,无形也加大了开发的难度
如果要进行延后执行,并且发现延后服务函数需要休眠,只能用工作队列
如果要进行延后执行,并且发现无休眠并且考虑效率,用tasklet
如果要进行延后执行,并且无休眠并且无效率考虑,用工作队列[安全]