前言

本次实验例程中断使用定时器替代使用的,实验结果确实没啥问题。如果使用硬件中断的话需要配置设备树,然后从设备树获取irq号,然后就是使用request_irq函数。剩下的就都一样了。

Linux实现底半部的机制主要有tasklet、工作队列、软中断和线程化irq。

一 tasklet

tasklet的使用较简单,它的执行上下文是软中断,执行时机通常是顶半部返回的时候。我们只需要定义tasklet及其处理函数,并将两者关联则可,例如:

void my_tasklet_func(unsigned long); /*定义一个处理函数*/
DECLARE_TASKLET(my_tasklet, my_tasklet_func, data);/*定义一个tasklet结构my_tasklet,与my_tasklet_func(data)函数相关联*/
#define DECLARE_TASKLET(name, func, data) \
struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(0), func, data }
#define DECLARE_TASKLET_DISABLED(name, func, data) \
struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(1), func, data }

代码DECLARE_TASKLET(my_tasklet,my_tasklet_func,data)实现了定义名称为my_tasklet的tasklet,并将其与my_tasklet_func()这个函数绑定,而传入这个函数的参数为data。在需要调度tasklet的时候引用一个tasklet_schedule()函数就能使系统在适当的时候进行调度运行:

tasklet_schedule(&my_tasklet);

tasklet结构体

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

使用tasklet作为底半部处理中断的设备驱动程序模板如下代码

 /* 定义tasklet和底半部函数并将它们关联 */void xxx_do_tasklet(unsigned long);DECLARE_TASKLET(xxx_tasklet, xxx_do_tasklet, 0);/* 中断处理底半部 */void xxx_do_tasklet(unsigned long){...}/* 中断处理顶半部 */irqreturn_t xxx_interrupt(int irq, void *dev_id){...tasklet_schedule(&xxx_tasklet);...}/* 设备驱动模块加载函数 */int __init xxx_init(void){.../* 申请中断 */result = request_irq(xxx_irq, xxx_interrupt,0, "xxx", NULL);...return IRQ_HANDLED;}/* 设备驱动模块卸载函数 */void __exit xxx_exit(void){.../* 释放中断 */free_irq(xxx_irq, xxx_interrupt);...}

上述程序在模块加载函数中申请中断,并在模块卸载函数中释放它。对应于xxx_irq的中断处理程序被设置为xxx_interrupt()函数,在这个函数中,tasklet_schedule(&xxx_tasklet)调度被定义的tasklet函数xxx_do_tasklet()在适当的时候执行。

二 在一个定时器中测试tasklet实例

完整测试源码

#include <linux/init.h>
#include <linux/module.h>
#include <linux/timer.h>
#include <linux/interrupt.h>#define DEBUG_TSK(format, ...)                                                                     \printk ("%s,line=%d:" format "\n", __func__, __LINE__, ##__VA_ARGS__)struct cstsk_dev_{struct timer_list timer;int count;struct tasklet_struct my_timer_tasklet;
};
static struct cstsk_dev_ global_cstsk_dev = {.count = 0,.my_timer_tasklet = {.next = NULL,.count = ATOMIC_INIT(0), .state = 0,},
};static void cstsk_tasklet_function(unsigned long arg)
{struct cstsk_dev_ *cstsk_dev = (struct cstsk_dev_ *)arg;DEBUG_TSK("cstsk_dev->count = %d",++cstsk_dev->count);
}static void cstsk_timer_function(unsigned long arg)
{struct cstsk_dev_ *cstsk_dev = (struct cstsk_dev_ *)arg;tasklet_schedule(&cstsk_dev->my_timer_tasklet);DEBUG_TSK("");mod_timer(&cstsk_dev->timer,jiffies + msecs_to_jiffies(1000));
}
static int __init cstsk_init(void)
{struct cstsk_dev_ *cstsk_dev = &global_cstsk_dev;init_timer(&cstsk_dev->timer);cstsk_dev->timer.data = (unsigned long)cstsk_dev;cstsk_dev->timer.function = cstsk_timer_function;  DEBUG_TSK("");    cstsk_dev->my_timer_tasklet.data = (unsigned long)cstsk_dev;cstsk_dev->my_timer_tasklet.func = cstsk_tasklet_function;mod_timer(&cstsk_dev->timer,jiffies + msecs_to_jiffies(1000));return 0;
}static void __exit cstsk_exit(void)
{struct cstsk_dev_ *cstsk_dev = &global_cstsk_dev;del_timer_sync(&cstsk_dev->timer);DEBUG_TSK("");
}module_init(cstsk_init);
module_exit(cstsk_exit);
MODULE_LICENSE("GPL");

Makefile文件

export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-
KERN_DIR = /home/lkmao/imx/linux/linux-imxFILE_NAME=csi_tasklet
obj-m += $(FILE_NAME).oall:make -C $(KERN_DIR) M=$(shell pwd) modules
.PHONY:clean
clean:make -C $(KERN_DIR) M=$(shell pwd) clean

测试结果:

加载以后就会一直在cstsk_tasklet_function函数中打印计数值。

root@hehe:~# insmod csi_tasklet.ko
[  658.303251] cstsk_init,line=43:
root@hehe:~# [  659.303344] cstsk_timer_function,line=34:
[  659.307384] cstsk_tasklet_function,line=27:cstsk_dev->count = 1
[  660.303341] cstsk_timer_function,line=34:
[  660.307370] cstsk_tasklet_function,line=27:cstsk_dev->count = 2
[  661.303336] cstsk_timer_function,line=34:
[  661.307363] cstsk_tasklet_function,line=27:cstsk_dev->count = 3
[  662.303345] cstsk_timer_function,line=34:
[  662.307385] cstsk_tasklet_function,line=27:cstsk_dev->count = 4
[  663.303332] cstsk_timer_function,line=34:
[  663.307362] cstsk_tasklet_function,line=27:cstsk_dev->count = 5

代码解析:

在模块初始化函数中,初始化定时器timer,将模块私有指针struct cstsk_dev_ *作为data传递给timer和tasklet。初始化tasklet相关参数,然后启动定时器timer,定时器timer间隔1秒。在定时器函数cstsk_timer_function中调用tasklet_schedule,调度tasklet,然后cstsk_tasklet_function就被执行了。

结束

linux内核中断实践2:tasklet相关推荐

  1. linux内核中断实践5:threaded_irq

    前言 这次实验就没办法使用定时器来忽悠了.在开发板上配按键和设备树.按键是上升沿和下降沿双向触发的.测试效果一级棒. Linux实现底半部的机制主要有tasklet.工作队列.软中断和线程化irq.本 ...

  2. Linux内核中断系统处理机制-详细分析

    原文地址::https://blog.csdn.net/weixin_42092278/article/details/81989449 相关文章 1.Linux中断管理 (1)Linux中断管理机制 ...

  3. 《linux内核中断》之 法外狂徒张三删库跑路

    法外狂徒张三删库跑路 真实案例:在今年2月份,国内一个程序员删库的消息传遍it界.他的几行代码,直接让上市公司微盟的市值一天蒸发超10亿,300百万用户直接受到影响.网上是谣言四起,可谓是最牛逼的删库 ...

  4. linux内核中断详解

    linux内核中断详解 1.中断的硬件触发流程 外设:如果外设有操作或者有数据可用,那么就会产生一个电信号,这个电信号发送给中断控制器. 中断控制器:中断控制器接收到外设发来的电信号以后,进行进一步的 ...

  5. linux内核看门狗关闭方法,linux内核中断之看门狗

    一:内核中断 linux内核中的看门狗中断跟之前的裸板的中断差不多,在编写驱动之前,需要线把内核自带的watch dog模块裁剪掉,要不然会出现错误:在Device Drivers /Watchdog ...

  6. Linux内核中断系统结构——软中断

    在 Linux异常(中断)处理体系结构 这篇文章,我们详细描写了内核如何进行中断(异常)向量表的初始化.如何初始化硬件中断(IRQ)的操作. 在这篇文章中,我们将重心放在软件中断上.也就是 CPU 本 ...

  7. Linux内核中断系统

    前言 中断在驱动中是非常常用的,无论是外部的GPIO中断,还是SPI,I2C等发送或接收中断,都是必不可少的.所以今天来看看Linux中的中断处理. 中断分类 上面我们根据中断来源,屏蔽方式和中断入口 ...

  8. Linux内核中断顶半部和底半部的理解

    工科生一枚,热衷于底层技术开发,有强烈的好奇心,感兴趣内容包括单片机,嵌入式Linux,Uboot等,欢迎学习交流! 爱好跑步,打篮球,睡觉. 欢迎加我QQ1500836631(备注CSDN),一起学 ...

  9. linux内核中断(一)

    一.中断简介 中断是指 CPU 在执行程序的过程中,出现了某些突发事件急待处理,CPU 必须暂停当前程序的执行, 转去处理突发事件,处理完毕后又返回原程序被中断的位置继续执行.由于中断的存在极大的提高 ...

最新文章

  1. 全网最全的Windows下Anaconda2 / Anaconda3里正确下载安装用来定时任务apscheduler库(图文详解)...
  2. Angular 2 DI系统中 函数forwardRef 的作用?
  3. java几点钟_实现 Java 本地缓存,该从这几点开始
  4. fail-fast与fail-safe工作机制
  5. C.One Piece
  6. CentOS 6.5+Syslog-ng+LogZilla搭建中央日志服务器
  7. 输入阻抗和输出阻抗的理解
  8. 华为服务器型号分类,解析华为服务器
  9. 博科导向器升级固件-U盘
  10. linux怎么卸载gdb,卸载GDB 包
  11. 浙大高分子物理郑强教授的激情演讲
  12. OS X 安装命令行看图工具 chafa 以及其依赖libtool
  13. 基于引导滤波的暗通道matlab,基于加权引导滤波的水下图像增强算法
  14. Java 语言程序设计基础(笔记一) ( 专升本自考 ,九天速成 )
  15. mysql一行数据拆分为多行数据
  16. [云原生专题-9]:容器 - Docker的启动与关闭:run、stop
  17. Java程序员从笨鸟到菜鸟之(二十一)java过滤器和监听器详解
  18. C#委托实现信用卡用户定时还款功能
  19. 实时 Linux 架构剖析
  20. Mybatis框架的一点个人心得

热门文章

  1. OpenCV 之BGR2YUV
  2. BZOJ 3758 数数 分段打表
  3. C++创建线程并操作临界资源
  4. Centos系统内存查看与缓存清理
  5. 【FinacialKnowledge】财务报表及名词解释
  6. STM32循迹小车/Android蓝牙控制小车(三)
  7. 操作留痕功能实现与探讨
  8. 关于如何使用QSS实现QPushButton QToolButton上的图片拉伸和文字对齐
  9. [适合非python新手]selenium自动化测试 4-浏览器插件
  10. 使用auto.js实现自动化每日打卡