tasklet

本文介绍了Linux内核中的Tasklet机制,包括其用途、注意事项、特征和接口等,并提供了一个简单的示例代码,展示了如何初始化、调度和销毁Tasklet。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 tasklet用途
 在中断处理中大量使用tasklet机制;tasklet 用于减少硬中断处理的时间,将本来是在硬中断服务程序中完成的任务转化成软中断完成,即是将一些非紧急的任务留到tasklet中完成,而紧急的任务则在硬中断服务程序中完成。

2 注意事项
 tasklet始终在中断期间和调度它的CPU上执行;调度一个tasklet只是告诉内核要在之后的某个时间来执行给定的函数。tasklet在“软件中断”上下文中要以原子模式执行,且在遵守以下规则:

      * 不允许访问用户空间;
      * 不允许访问current指针;
      * 不能执行休眠或调度。

3 tasaklet 特征
 * 一个tasklet可被禁用或启用;只用启用的次数和禁用的次数相同时,tasklet才会被执行;
 * 和定时器类似,tasklet可以注册自己;
 * tasklet可被调度在一般优先级或者高优先级上执行,高优先级总会首先执行;
 * 如果系统负荷不重,则tasklet会立即得到执行,且始终不会晚于下一个定时器滴答;
 * 一个tasklet可以和其他tasklet并发,但对自身来讲必须严格串行处理,即一个tasklet
   不会在多个处理器上执行。

4 tasklet 结构
  1. #include <linux/interrupt.h>
  2. struct tasklet_struct
  3. {
  4.     struct tasklet_struct *next;
  5.     unsigned long state;
  6.     atomic_t count;
  7.     void (*func)(unsigned long);   /* 指向要被调度执行的函数 */
  8.     unsigned long data;            /* 传递给函数func的参数 */
  9. };
5 tasklet接口
  1. void tasklet_init(struct tasklet_struct *t, void (*func)(unsigned long),
  2.      unsigned long data); /* 初始化tasklet,func指向要执行的函数,data为传递给函数func的参数 */
  3. DECLARE_TASKLET(name,func,data); /*定义及初始化tasklet*/
  4. DECLARE_TASKLET_DISABLED(name,func,data);      /*定义及初始化后禁止该tasklet*/
  5. void tasklet_disable(struct tasklet_struct *t) /*禁用指定tasklet*/
  6. void tasklet_disable_nosync(struct tasklet_struct *t) /*禁用指定tasklet,但不会等待任何正在
  7.                                                         运行的tasklet退出*/
  8. void tasklet_enable(struct tasklet_struct *t)      /*启用先前被禁用的tasklet*/
  9. void tasklet_schedule(struct tasklet_struct *t)    /*调度执行指定的tasklet*/
  10. void tasklet_hi_schedule(struct tasklet_struct *t) /*调度指定的tasklet以高优先级执行*/
  11. void tasklet_kill(struct tasklet_struct *t)        /*移除指定tasklet*/
6 示例代码     tasklet.rar  
  这里并没有在中断中使用tasklet,而是在加载模块时简单地使用它。

点击(此处)折叠或打开

  1. #include <linux/module.h>
  2. #include <linux/init.h>
  3. #include <linux/interrupt.h>
  4. #include <linux/jiffies.h>

  5. MODULE_LICENSE("Dual BSD/GPL");
  6. MODULE_AUTHOR("Kozo");
  7. static struct tasklet_struct display_tasklet;

  8. static void display(unsigned long data)
  9. {
  10.     printk(KERN_DEBUG"before schedule:%d, in running:%d\n",data,jiffies);
  11. }
  12. static int __init demo_init(void)
  13. {
  14.     unsigned long tmp;
  15.     tmp = jiffies;
  16.     tasklet_init(&display_tasklet, display, tmp);
  17.     tasklet_schedule(&display_tasklet);
  18.     return 0;
  19. }

  20. static void __exit demo_exit(void)
  21. {
  22.     printk(KERN_ALERT"Goodbye\n");
  23.     tasklet_kill(&display_tasklet);
  24. }
  25. module_init(demo_init);
  26. module_exit(demo_exit);
7 执行结果

 从这里的jiffies值输出可以看出,在调度tasklet之后,tasklet在下一个滴答之前被执行。
### 使用 `tasklet_setup` 函数 在 Linux 内核编程中,`tasklet_setup` 函数用于初始化并设置 tasklet 结构体。Tasklet 是一种软中断机制,允许延迟执行某些任务而不阻塞当前进程。通过该函数可以指定要执行的任务及其名称。 #### 初始化 Tasklet 为了创建一个新的 tasklet 并将其关联到具体的回调函数上,需要定义一个结构体变量并通过 `tasklet_setup` 来完成初始化工作: ```c #include <linux/interrupt.h> // 定义 tasklet 处理程序 void my_tasklet_handler(unsigned long data); struct tasklet_struct my_tasklet; static int __init init_module(void) { // 初始化 tasklet, 设置 handler 和 name tasklet_setup(&my_tasklet, my_tasklet_handler); // 调度 tasklet 执行 tasklet_schedule(&my_tasklet); return 0; } ``` 上述代码展示了如何声明和初始化一个名为 `my_tasklet` 的 tasklet 实例,并指定了当这个 tasklet 需要运行时应该调用哪个处理函数[^1]。 #### 注册 Tasklet Handler 接下来就是实现实际的 tasklet 处理逻辑部分——即编写相应的处理器函数。这里需要注意的是,由于 tasklet 运行于中断上下文中,因此不能在此处睡眠或等待其他资源释放;否则可能导致系统死锁等问题发生。 ```c void my_tasklet_handler(unsigned long data) { printk(KERN_INFO "Executing tasklet handler\n"); // 在此处放置想要推迟执行的具体操作... } ``` 这段简单的例子仅打印了一条消息表示正在执行 tasklet 处理器。实际上可以根据需求在这里加入更复杂的数据处理流程或其他异步事件响应行为[^2]。 #### 取消已安排的 Tasklet 有时可能希望取消之前已经安排好但尚未触发执行的 tasklet 。这可以通过调用 `tasklet_kill` 函数来实现: ```c static void __exit cleanup_module(void) { // 如果 tasklet 正在排队,则等待其完成后再销毁它 tasklet_kill(&my_tasklet); } module_init(init_module); module_exit(cleanup_module); ``` 此段代码确保模块卸载前任何未决的 tasklet 请求都能得到妥善清理,从而避免潜在的风险隐患[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值