RK3568驱动指南|第五期-中断-第44章 共享工作队列实验

news2024/11/27 18:44:32

瑞芯微RK3568芯片是一款定位中高端的通用型SOC,采用22nm制程工艺,搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码,支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU,可用于轻量级人工智能应用。RK3568 支持安卓 11 和 linux 系统,主要面向物联网网关、NVR 存储、工控平板、工业检测、工控盒、卡拉 OK、云终端、车载中控等行业。


【公众号】迅为电子

【粉丝群】824412014(加群获取驱动文档+例程)

【视频观看】嵌入式学习之Linux驱动(第五期_中断_全新升级)_基于RK3568

【购买链接】迅为RK3568开发板瑞芯微Linux安卓鸿蒙ARM核心板人工智能AI主板


第44章 共享工作队列实验

在上个章节我们学习了中断下文的一种实验方式——软中断,本章节我们来学习中断下文的另一种实现方式——工作队列。工作队列是操作系统中管理和调度异步任务执行的一种机制,接下来开始学习工作队列吧。

44.1 什么是工作队列

工作队列是实现中断下半部分的机制之一,是一种用于管理任务的数据结构或机制。它通常用于多线程,多进程或分布式系统中,用于协调和分配待处理的任务可用的工作线程或工作进程

工作队列的基本原理是将需要执行的任务按顺序排列在队列中,并提供一组工作线程或者工作进程来处理队列中的任务。当有新的任务到达时,它们会被添加到队列的末尾,工作线程或工作进程从队列的头部获取任务,并执行相应的处理操作。

工作队列和之前学习的tasklet有什么不同呢?tasklet也是实现中断下半部分的机制之一。他们最主要的区别是tasklet不能休眠,而工作队列是可以休眠的,所以tasklet可以用来处理比较耗时间的事情,而工作队列可以处理更耗时间的事情。

工作队列将工作推后以后,会交给内核线程去执行。Linux在启动过程中会创建一个工作者内核线程,这个线程创建以后处于sleep状态。当有工作需要处理的时候,会唤醒这个线程去处理工作。

在内核中,工作队列包括共享工作队列和自定义工作队列这俩种类型。这两种类型的工作队列具有不同的特点和用途。

1  共享队列是由内核管理的全局工作队列,用于处理内核中一些系统级任务。共享工作队列是内核中一个默认工作队列,可以由多个内核组件和驱动程序共享使用。

2 自定义工作队列是由内核或驱动程序创建的特定工作队列,用于处理特定的任务。自定义工作队列通常与特定的内核模块或驱动程序相关联,用于执行该模块或驱动程序相关的任务。

 本章节我们先来学习共享工作队列相关的知识。

在Linux 内核中,使用 work_struct 结构体表示一个工作项,这些工作组织成工作队列,工作队列使用 workqueue_struct 结构体表示,如下图所示,流水线相当于工作队列,流水线上一个个等待处理的物料相当于一个个工作。机器相当于内核线程或进程。

图 44-1

work_struct 结构体表示一个工作项,定义在include/linux/workqueue.h中,如下所示:

struct work_struct {
 atomic_long_t data; 
 struct list_head entry;
 work_func_t func; /* 工作队列处理函数 */
};
typedef void (*work_func_t)(struct work_struct *work);  //工作函数

44.2 工作队列相关接口函数

44.2.1 初始化函数

在实际的驱动开发中,我们只需要定义工作项(work_struct)即可,关于工作队列和工作者线程我们基本不用去管。简单创建工作很简单,直接定义一个 work_struct 结构体变量即可,然后使用 INIT_WORK 宏来初始化工作,INIT_WORK 宏定义如下:

#define INIT_WORK(_work,_func)

INIT_WORK 宏接受两个参数:_work 和 _func,分别表示要初始化的工作项和工作项的处理函数。

也可以使用 DECLARE_WORK 宏一次性完成工作的创建和初始化,宏定义如下:

#define DECLARE_WORK(n, f)

参数n 表示定义的工作(work_struct),f 表示工作对应的处理函数。

44.2.2 调度/取消调度工作队列函数

和 tasklet 一样,工作也是需要调度才能运行的,工作的调度函数为 schedule_work,函数原型如下所示:

static inline bool schedule_work(struct work_struct *work)

参数是指向工作项的指针。这个函数作用是将工作项提交到工作队列中,并请求调度器在合适的时机执行工作项。该函数会返回一个布尔值,表示工作项是否成功被提交到工作队列。

如果想要取消该工作项的调度,使用以下函数:

bool cancel_work_sync(struct work_struct *work);

参数是指向工作项的指针。这个函数的作用是取消该工作项的调度。如果工作项已经在工作队列中,它将被从队列中移除。如果工作项已经在工作队列中,它将被从队列中移除,并等待工作项执行完成。函数返回一个布尔值,表示工作项是否成功取消。

44.3 实验程序的编写

44.3.1 驱动程序编写

本实验对应的网盘路径为:iTOP-RK3568开发板【底板V1.7版本】\03_【iTOP-RK3568开发板】指南教程\02_Linux驱动配套资料\04_Linux驱动例程\34_workqueue\module

本实验将实现注册显示屏触摸中断,每按当触摸LCD显示屏就会触发中断服务函数,在中断服务函数中提交工作项到共享工作队列中,打印“This id test_interrupt”和“This is test_work”。

在驱动程序中的模块初始化函数中,我们将GPIO转换为中断号,并使用request_irq函数请求中断,然后初始化工作项。当中断被触发时,中断处理函数被调用,并将工作项提交到共享工作队列中,最终由工作项处理函数异步执行。编写完成的interrupt.c代码如下所示,添加的代码已加粗表示。

#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/workqueue.h>
int irq;
struct work_struct test_workqueue;
// 工作项处理函数
void test_work(struct work_struct *work)
{
  msleep(1000);
  printk("This is test_work\n");
}
// 中断处理函数
irqreturn_t test_interrupt(int irq, void *args)
{
  printk("This is test_interrupt\n");
  // 提交工作项到工作队列
  schedule_work(&test_workqueue);
  return IRQ_RETVAL(IRQ_HANDLED);
}

static int interrupt_irq_init(void)
{
  int ret;
  irq = gpio_to_irq(101); // 将GPIO映射为中断号
  printk("irq is %d\n", irq);
  // 请求中断
  ret = request_irq(irq, test_interrupt, IRQF_TRIGGER_RISING, "test", NULL);
  if (ret < 0)
  {
    printk("request_irq is error\n");
    return -1;
  }
  // 初始化工作项
  INIT_WORK(&test_workqueue, test_work);
  return 0;
}

static void interrupt_irq_exit(void)
{
  free_irq(irq, NULL); // 释放中断
  printk("bye bye\n");
}
module_init(interrupt_irq_init);
module_exit(interrupt_irq_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("topeet");

44.4 运行测试

44.4.1 编译驱动程序

在上一小节中的interrupt.c代码同一目录下创建 Makefile 文件,Makefile 文件内容如下所示:

export ARCH=arm64#设置平台架构
export CROSS_COMPILE=aarch64-linux-gnu-#交叉编译器前缀
obj-m += interrupt.o    #此处要和你的驱动源文件同名
KDIR :=/home/topeet/Linux/linux_sdk/kernel    #这里是你的内核目录                                                                                                                            
PWD ?= $(shell pwd)
all:
    make -C $(KDIR) M=$(PWD) modules    #make操作
clean:
    make -C $(KDIR) M=$(PWD) clean    #make clean操作

对于Makefile的内容注释已在上图添加,保存退出之后,来到存放interrupt.c和Makefile文件目录下,如下图(图44-2)所示:

图 44-2

然后使用命令“make”进行驱动的编译,编译完成如下图(图44-3)所示:

图 44-3

编译完生成interrupt.ko目标文件,如下图(图44-4)所示:

图 44-4

至此驱动模块就编译成功了,接下来进行测试。

44.4.2 运行测试

开发板启动之后,使用以下命令进行驱动模块的加载,如下图(图44-5)所示:

insmod interrupt.ko

图44-5

加载驱动之后,可以看到申请的中断号被打印了出来,然后用手触摸连接的LVDS 7寸屏幕,打印如下图(44-6)所示:

在上图中,可以看到打印中断处理函数中添加的打印“This is test_interrupt”被多次打印,说明触发了好几次中断上文,那么中断上文会多次调度中断下文,所以也会打印工作项处理函数中添加的打印“This is test_work”。但是为什么只会打印俩次“This is test_work”呢?这是因为在中断上文调度工作项处理函数之后,内核没有来得及去执行工作项处理函数,没有执行相当于无效操作,有效的执行则打印了俩次“This is test_work”。

最后可以使用以下命令进行驱动的卸载,如下图(图44-7)所示:

rmmod interrupt

 

图 44-7

至此,共享工作队列实验就完成了。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1042229.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023年深圳等保测评机构名称以及地址汇总

你知道深圳等保测评机构有哪些&#xff1f;知道在哪里吗&#xff1f;今天我们小编就给大家汇总一下。 2023年深圳等保测评机构名称以及地址汇总 序号&#xff1a;1 名称&#xff1a;深圳市信息安全管理中心 地址&#xff1a;深圳市福田区莲花街道福中路城市数字资源中心 序…

CMake 官方完整版

CMake 官方完整版 一些概念TargetSignature 1. A Basic Starting Point(Step 1)Adding a Version Number and Configured Header FileSpecify the C StandardBuild and Test 2. Adding a Library(Step 2)-添加一个库Adding an Option 3. Adding Usage Requirements for Library…

【Verilog 教程】4.8Verilog 过程连续赋值

关键词&#xff1a;deassign&#xff0c;force&#xff0c;release 过程连续赋值是过程赋值的一种。这种赋值语句能够替换其他所有 wire 或 reg 的赋值&#xff0c;改写了 wire 或 reg 型变量的当前值。 与过程赋值不同的是&#xff0c;过程连续赋值的表达式能被连续的驱动到 …

pinyin-match选择器拼音快速检索目标

npm地址&#xff1a;https://www.npmjs.com/package/pinyin-match 选择器拼音快速检索目标&#xff08;pinyin-match&#xff09; 一. 使用方法二. 使用实例三. 实现效果 一. 使用方法 安装 pinyin-match 包 yarn add pinyin-match 或 npm install pinyin-match --save 引入 …

3分钟,免费制作一个炫酷实用的数据可视化大屏!

在当前大数据时代背景下&#xff0c;数据已成为在工业革命中如同煤炭、石油一般宝贵的资源。但是由于数据越来越庞大、越来越复杂&#xff0c;导致数据的可读性也越来越低。因此&#xff0c;对数据可视化的需求也越来越高&#xff0c;需要解决的问题也越来越复杂&#xff0c;而…

测试工程师高效编写API测试

1、自动化测试流程 我一直有编写自动化测试的习惯&#xff0c;但之前一直没有达到最理想的效果&#xff0c;也在反思问题出现的原因&#xff0c;最近终于有了一些思路。其主要的原因是之前写测试都是靠感觉&#xff0c;感觉哪些需要测试了&#xff0c;就写一个测试&#xff0c…

【面试必刷TOP101】二分查找-I 二维数组中的查找

目录 题目&#xff1a;二分查找-I_牛客题霸_牛客网 (nowcoder.com) 题目的接口&#xff1a; 解题思路&#xff1a; 代码&#xff1a; 过啦&#xff01;&#xff01;&#xff01; 题目&#xff1a;二维数组中的查找_牛客题霸_牛客网 (nowcoder.com) 题目的接口&#xff1…

emacs怎么安装插件

2023年9月26日&#xff0c;周二下午 目录 Linux下Emacs的配置文件位置包管理器elpa怎么给elpa换源罗列可按照的插件怎么搜索插件怎么安装插件配置插件 Linux下Emacs的配置文件位置 默认配置文件位置是 ~/.emacs 或 ~/.emacs.d/init.el 如果没有inti.el的话&#xff0c;自己创…

产品经理如何进行项目管理?

在网上总是有人认为产品经理和项目经理不是一路人&#xff0c;工作上也没有什么共性&#xff0c;认为项目管理仅仅是项目经理的活&#xff0c;其实不然。一个项目从初始到结束这一整个周期&#xff0c;产品经理都是需要全程盯着的。 那么优秀的产品经理是怎么管理项目的呢&…

7、如何使用Flink中的窗口(Window算子)

目录 1、如何理解 Flink中的窗口&#xff08;window&#xff09; 2、Flink中窗口的类型 2.1 根据上游DataStream类型分类 2.2 根据驱动类型分类 2.3 根据进入到窗口数据的分发规则分类 3、怎样使用 Flink中的 Window算子 4、怎样使用 Flink中的 Window Assigners 4.1、…

Python 进阶 - 日常工作中使用过的简单Trick

引言&#xff1a;无论你是一名初学者还是有一定经验的开发者&#xff0c;这些技巧都能帮助你更好地利用Python来解决问题、提高效率和写出更干净、可维护的代码。无论你是数据科学家、Web开发者、自动化脚本编写者还是其他领域的从业者&#xff0c;这些技巧都能对你有所帮助。 …

Linux 日期、时区

1、date命令 通过date命令可以在命令行中查看系统的时间 date [-d] [格式化字符串] -d 按照给定的字符串显示日期&#xff0c;一般用于日期计算 格式化字符串&#xff1a;通过特定的字符串标记&#xff0c;来控制显示的日期格式 %Y 年 %y 年份后两位数字 (00..99) %m …

【百度地图】绘制扇形图层

思路&#xff1a;使用多边形图层PolygonLayer&#xff0c;借助函数将一个经纬度转换成扇形经纬度数组 扇形经纬度数组生成函数 /** 返回扇形经纬度数组 绘制多边形* lon 经度* lat 维度* radius 半径* azimuth 方向角* jiaodu&#xff08;扇形的夹角&#xff09;** **/ export…

java Spring Boot2.7写一个接口 提供图片预览 前端可以直接用接口地址当src为图片地址使用

我们特别是在做小程序开发时 很多图片会比较大 而小程序本身就对自身大小要求非常高 所以 图片放在服务器上提供访问链接是一种非常好的选择 我想很多前端会误认为 直接将图片放在服务器上就可以了 但其实没那么简单 因为服务器其实也可以理解为一个电脑 你就想 你自己本地都不…

python+requests+pytest+allure自动化框架

1.核心库 requests request请求 openpyxl excel文件操作 loggin 日志 smtplib 发送邮件 configparser unittest.mock mock服务 2.目录结构 base utils testDatas conf testCases testReport logs 其他 2.1base base_path.py 存放绝对路径,dos命令或Jenkins执行…

idea Springboot闲置物品交易平台VS开发mysql数据库web结构java编程计算机网页源码maven项目

一、源码特点 springboot 闲置物品交易平台是一套完善的完整二手交易信息系统&#xff0c;结合springboot框架和bootstrap完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用springboot框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统具有完整的源代…

Wespeaker框架训练(2)

2. 模型训练 2.1 run.sh stage 3 数据集处理完毕后开始训练&#xff0c;主要是调用wespeaker/bin/train.py 函数 echo ”Start training ...” 打印提示信息&#xff0c;表示开始训练num_gpus$(echo $gpus | awk -F ’,’ ’print NF’) 通过gpus 变量获取要使用的GPU 数量t…

《C++ primer》练习6.36-6.38:书写返回数组引用的函数声明

最近看C primer&#xff0c;看到《C primer》6.3.3练习&#xff0c;要求书写返回数组引用的函数声明&#xff0c;觉得有必要实践记录一下。 这里先总结返回数组的引用的的函数声明写法&#xff08;下面的Type是数组元素的类型&#xff0c;可以是int、float等&#xff0c;如果要…

企业架构相关

数据架构的作用首先是找到所有的业务对象 和数据对象。 在数据对象分析里面有一个重点就是主数据识别和分析。