查看: 1434|回复: 0

芯灵思SinlinxA64开发板Linux内核 tasklet 机制(附实测代码)

[复制链接]
  • TA的每日心情
    奋斗
    2016-4-14 10:16
  • 签到天数: 9 天

    连续签到: 1 天

    [LV.3]偶尔看看II

    发表于 2019-3-12 16:45:30 | 显示全部楼层 |阅读模式
    分享到:
    Linux 中断编程分为中断顶半部,中断底半部
    中断顶半部: 做紧急,耗时短的事情,同时还启动中断底半部。
    中断底半部: 做耗时的事件,这个事件在执行过程可以被中断。
    中断底半部实现方法: tasklet,工作队列,软中断等机制实现。实际上是把耗时事件推后执行,不在中断程序执行。

    什么是tasklet?
    Tasklet 一词的原意是“小片任务”的意思,这里是指一小段可执行的代码,且通常以函数的形式出现。这个 tasklet 绑定的函数在一个时刻只能在一个 CPU 上运行  ,tasklet(小任务)机制是中断处理下半部分最常用的一种方法,其使用也是非常简单的。一个使用 tasklet 的中断程序首先会通过执行中断处理程序来快速完成上半部分的工作,接着通过调用 tasklet 使得下半部分的工作得以完成。可以看到,下半部分被上半部分所调用,至于下半部分何时执行则属于内核的工作。

    tasklet 机制核心数据结构

    tasklet 机制核心数据结构
    Interrupt.h linux-3.5\include\Linux
    struct tasklet_struct
    {
          struct tasklet_struct *next; // tasklet_struct 结构链表
          unsigned long state; //当前这个 tasklet 是否已经被调度
          atomic_t count;
          void (*func)(unsigned long); //指向 tasklet 绑定的函数的指针
          unsigned long data; //传递给tasklet 绑定的函数的参数

    };

    tasklet 相关 API
    初始化相关
    1. 静态初始化 DECLARE_TASKLET(name, func, data)
    作用:定义一个名字为 name 的 tasklet_struct 结构变量,并且初始化这个结构。 所定义的这个 tasklet 是可以被调度,默认是处于被使能状态。

    2. 静态初始化 DECLARE_TASKLET_DISABLED(name, func, data)
    作用:定义一个名字为 name 的 tasklet_struct 结构变量,并且初始化这个结构。所定义的这个 tasklet 是不能被调度,默认是处于被禁能状态。 要调度这个 tasklet 需要先使能。

    3.动态初始化
    void tasklet_init(struct tasklet_struct *t,void (*func)(unsigned long), unsigned long data)
    作用:初始化一个 tasklet_struct 结构变量,初始化的结构默认是处于激活状态,可以被调度。

    tasklet使能函数
    1. void tasklet_disable(struct tasklet_struct *t)
    作用:函数激活给定的 tasklet被 tasklet_schedule 调度
    2. void tasklet_enable (struct tasklet_struct *t)
    作用:函数禁止给定的 tasklet被 tasklet_schedule 调度
    tasklet 调度函数  
    void tasklet_schedule (struct tasklet_struct *t)
    作用:调用 tasklet_schedule 函数去通知内核帮我们调度所绑定的函数
    void tasklet_kill(struct tasklet_struct *t);
    作用:取消调度函数
    编程步骤
    Step1  定义并静态初始化tasklet_struct 结构变量
    Step2  编写tasklet服务函数
    Step3  在适当的地地方进行调度
    Step4  在适当的地地方取消调度


    实验平台:芯灵思SINA64开发板
    嵌入式linux 开发板交流 QQ:641395230
    驱动代码:
    1. #include <linux/module.h>
    2. #include <linux/init.h>
    3. #include <linux/interrupt.h>

    4. void tasklet_fun(unsigned long data);
    5. //Step1 定义并静态初始化tasklet_struct 结构变量
    6. DECLARE_TASKLET(mytasklet, tasklet_fun, 651);
    7. //Step2 tasklet服务函数
    8. void tasklet_fun(unsigned long data)
    9. {
    10.         static unsigned long count = 0;
    11.         printk("count:%lu,%s is call! data:%lu\r\n",count++,__FUNCTION__,data);
    12.         tasklet_schedule(&mytasklet); //在工作函数中重新调度自己,这样会循环调用tasklet_fun
    13. }
    14. static int __init mytasklet_init(void)
    15. {
    16.         //Step3 开始调度 mytasklet
    17.         tasklet_schedule(&mytasklet);
    18.         printk("%s is call!\r\n",__FUNCTION__);
    19.         return 0;
    20. }
    21. static void __exit mytasklet_exit(void) //Module exit function specified by module_exit()
    22. {
    23.         //Step4 删除 tasklet
    24.         tasklet_kill(&mytasklet);
    25. }
    26. module_init(mytasklet_init);
    27. module_exit(mytasklet_exit);
    28. MODULE_LICENSE("GPL");
    复制代码







    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    手机版|小黑屋|与非网

    GMT+8, 2024-11-19 20:17 , Processed in 0.107702 second(s), 15 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.