中断下文之tasklet -29
2021/6/15 10:54:43
本文主要是介绍中断下文之tasklet -29,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
中断下文之tasklet
tasklet相关知识点
什么是 tasklet?
tasklet 是中断处理中断下文常用的一种方法,tasklet,是一种特殊的软中断。处理中断下文的机制还有工作队列和软中断。
怎么使用tasklet来设计中断下文?
中断发生 》》》》 中断上文,在中断处理一些紧急的事情 》》》》 调用tasklet 》》》》 中文下文,在中断下文做比较耗时的事情
Linux把中断分成俩个部分,一个是上半部分,一个是下半部分,在上半部分我们只处理紧急的事情,同时可以调用tasklet来启动中断下文,比较耗时间的就要放到下文来处理,调用tasklet以后,tasklet绑定的函数并不会立马执行,而是出中断以后,经过一个很短的不确定时间在来执行。
tasklet定义
tasklet由tasklet_struct结构表示,每个结构体单独代表一个tasklet,在<linux/interrupt.h>中定义为:
struct tasklet_struct { struct tasklet_struct *next; unsigned long state; atomic_t count; void (*func)(unsigned long); unsigned long data; };
- next:链表中的下一个 tasklet,方便管理和设置tasklet;
- state: tasklet 的状态。
- count:表示 tasklet,是否出在激活状态,如果是0,就处在激活状态,如果非0,就处在非激活状态
- void(*func)(unsigned long):结构体中的 func成员是tasklet的绑定函数,data是它唯一的参数。
- date:函数执行的时候传递的参数
tasklet相关函数
-
tasklet schedule函数
作用:调度tasklet
函数原型:
void tasklet_schedule(struct tasklet struct *t)
参数:
- 指向tasklet struct结构的指针。
-
tasklet_init函数
作用:动态初始化 tasklet
函数原型:
void tasklet_init(struct tasklet struct *t, void(*func)(unsigned long), unsigned long data);
参数:
- *t:指向tasklet_struct结构的指针。
- func: tasklet绑定的函数。
- data:函数执行的时候传递的参数。
- tasklet_kill函数
功能:删除一个 tasklet
函数原型:
tasklet_kill(struct tasklet_struct*t)
参数:
- 指向tasklet_ struct结构的指针
- 注意:这个函数会等待tasklet 执行完毕,然后再将它移除。该函数可能会引起休眠,所以要禁止在中断上下文中使用。
使用tasklet设计中断下文步骤
- 步骤一:定义一个tasklet结构体
- 步骤二:动态初始化tasklet
- 步骤三:编写tasklet绑定的函数
- 步骤四:在中断上文调用tasklet
- 步骤五:卸载模块的时候删除tasklet
代码点击屏幕触发
- driver1.c
#include <linux/init.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/errno.h> #include <linux/ioport.h> #include <linux/miscdevice.h> #include <linux/fs.h> #include <linux/uaccess.h> #include <linux/io.h> #include <linux/gpio.h> #include <linux/of_gpio.h> #include <linux/interrupt.h> #include <linux/of_irq.h> int gpio_num; int irq = 0; struct device_node *test_device_node; struct property *test_node_property; struct tasklet_struct key_tesk; struct of_device_id of_match_table[] = { {.compatible = "test_keys"}, {} }; irq_handler_t test_key(int irq, void *args){ printk("test_key start \n"); tasklet_schedule(&key_tesk); printk("test_key end \n"); return IRQ_HANDLED; } void test(unsigned long data){ int i = data; while (i--) { printk("task_key long time is %d \n", i); } } int beep_probe(struct platform_device *pdev){ int ret = 0; printk("beep_probe 匹配成功了 \n"); test_device_node = of_find_node_by_path("/test_key"); if (test_device_node == NULL) { printk("of_find_node_by_path is error \n"); return -1; } gpio_num = of_get_named_gpio(test_device_node, "touch-gpio", 0); if (gpio_num < 0) { printk("of_get_named_gpio is error \n"); return -1; } gpio_direction_input(gpio_num); //irq = gpio_to_irq(gpio_num); irq = irq_of_parse_and_map(test_device_node, 0); printk("irq is %d \n", irq); ret = request_irq(irq, test_key, IRQF_TRIGGER_RISING, "test_key", NULL); if (ret < 0) { printk("request_irq is error \n"); return ret; } tasklet_init(&key_tesk, test, 100); return 0; } int beep_remove(struct platform_device *pdev){ printk("beep_remove \n"); return 0; } const struct platform_device_id beep_idtable = { .name = "test_keys" }; struct platform_driver beep_device = { .probe = beep_probe, .remove = beep_remove, .driver = { .name = "123", .owner = THIS_MODULE, .of_match_table = of_match_table }, .id_table = &beep_idtable }; static int beep_driver_init(void){ printk(KERN_EMERG "hello world enter \n"); int ret = 0; ret = platform_driver_register(&beep_device); if (ret < 0) { printk("platform_driver_register 失败\n"); } printk("platform_driver_register ok\n"); return 0; } static void beep_driver_exit(void){ printk(KERN_EMERG "hello world exit! \n"); tasklet_kill(&key_tesk); free_irq(irq, NULL); platform_driver_unregister(&beep_device); } module_init(beep_driver_init); module_exit(beep_driver_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("LIYU");
设备树的代码
将下面的代码注释
touch-gpio = <&gpio1 20 IRQ_TYPE_EDGE_RISING>; interrupt-parent = <&gpio1>; interrupts = <20 IRQ_TYPE_LEVEL_LOW>;
然后在根节点中添加下面的代码
test_key { compatible = "test_keys"; pinctrl-names = "default"; pinctrl-0 = <&i2c1_xfer>; reg = <0x38>; touch-gpio = <&gpio1 20 IRQ_TYPE_EDGE_RISING>; interrupt-parent = <&gpio1>; interrupts = <20 IRQ_TYPE_LEVEL_LOW>; };
这篇关于中断下文之tasklet -29的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-05-09“2024鸿蒙零基础快速实战-仿抖音App开发(ArkTS版)”实战课程已上线
- 2024-05-09聊聊如何通过arthas-tunnel-server来远程管理所有需要arthas监控的应用
- 2024-05-09log4j2这么配就对了
- 2024-05-09nginx修改Content-Type
- 2024-05-09Redis多数据源,看这篇就够了
- 2024-05-09Google Chrome驱动程序 124.0.6367.62(正式版本)去哪下载?
- 2024-05-09有没有大佬知道这种数据应该怎么抓取呀?
- 2024-05-09这种运行结果里的10.100000001,怎么能最快改成10.1?
- 2024-05-09企业src漏洞挖掘-有意思的命令执行
- 2024-05-08阿里云域名注册流程,分享给第一次购买域名的新手站长!