Linux设备驱动器 之一 工作(worker)线程

Linux设备驱动器之一 工作线程

  • 数据结构
  • Linux APIs
    • 产生工作线程 kthread_create_worker
    • 初始化工作 kthread_init_work
    • 排队工作 kthread_queue_work
  • 在Linux中的应用实列
    • SPI 驱动器与imx SPI
      • 任务工作线程代码
      • 启动任务工作线程
  • 工作线程(worker)
    • Linux管理线程

数据结构

struct kthread_worker {unsigned int        flags;raw_spinlock_t      lock;struct list_head    work_list;struct list_head    delayed_work_list;struct task_struct  *task;struct kthread_work *current_work;
};struct kthread_work {struct list_head    node;kthread_work_func_t func;struct kthread_worker   *worker;/* Number of canceling calls that are running at the moment. */int         canceling;
};struct kthread_delayed_work {struct kthread_work work;struct timer_list timer;
};

Linux APIs

产生工作线程 kthread_create_worker

struct kthread_worker *kthread_create_worker(unsigned int flags, const char namefmt[], …)

  1. unsigned int flags : 指定任务工作线程默认行为
  2. const char namefmt[] : kthread 任务工作线程的printf样式名称。
  3. … : 变量参数

如果成功,则返回一个指针, 它指向已产生的任务工作线程;
如果无法分配所需的结构,则返回 ERR_PTR(-ENOMEM);
如果调用者收到一个致命信号,则返回 ERR_PTR(-EINTR)。

初始化工作 kthread_init_work

kthread_init_work(work, fn)
这是一个宏定义,它初始化struct kthread_work结构变量work, 并设置fn为完成该工作的程序代码。就是调用fn去完成需要的工作。

排队工作 kthread_queue_work

bool kthread_queue_work(struct kthread_worker *worker, struct kthread_work *work)
功能: 排队一个kthread_work
参数:

  1. struct kthread_worker *worker : 任务工作线程
  2. struct kthread_work *work: 需要排队的工作

将工作排队到工作处理器任务以进行异步执行。任务必须已使用 kthread_worker_create() 创建。如果工作已成功排队,则返回 true;如果工作已处于挂起状态,则返回 false。
如果工作需要由其他任务工作线程使用,请重新初始化该工作。例如,当任务工作线程停止并再次启动时。

在Linux中的应用实列

SPI 驱动器与imx SPI

spi_init_queue调用kthread_create_worker,kthread_init_work, 去产生SPI任务工作线程,细节见下面的代码段。

static int spi_init_queue(struct spi_controller *ctlr)
{ctlr->running = false;ctlr->busy = false;ctlr->kworker = kthread_create_worker(0, dev_name(&ctlr->dev));if (IS_ERR(ctlr->kworker)) {dev_err(&ctlr->dev, "failed to create message pump kworker\n");return PTR_ERR(ctlr->kworker);}kthread_init_work(&ctlr->pump_messages, spi_pump_messages);/** Controller config will indicate if this controller should run the* message pump with high (realtime) priority to reduce the transfer* latency on the bus by minimising the delay between a transfer* request and the scheduling of the message pump thread. Without this* setting the message pump thread will remain at default priority.*/if (ctlr->rt)spi_set_thread_rt(ctlr);return 0;
}

imx SPI 驱动器支持NXP i.MX 8M Nano。
下列的流程图描绘了imx SPI 驱动器如何调用spi_init_queue去初始化任务工作线程。

Created with Raphaël 2.3.0 spi_imx_probe imx 专用初始化 spi_bitbang_start 结束
Created with Raphaël 2.3.0 spi_bitbang_start spi_bitbang_init bitbang初始化成功 ? spi_register_master 结束 yes no

spi_register_master 由下列的宏定义

#define spi_register_master(_ctlr)  spi_register_controller(_ctlr)
Created with Raphaël 2.3.0 spi_register_controller spi_controller_initialize_queue 结束
Created with Raphaël 2.3.0 spi_controller_initialize_queue spi_init_queue 结束

任务工作线程代码

static void spi_pump_messages(struct kthread_work *work)

Created with Raphaël 2.3.0 spi_pump_messages __spi_pump_messages 结束
Created with Raphaël 2.3.0 __spi_pump_messages 任务工作线程空闲 ? prepare_transfer_hardware, 来自SPI控制结构 prepare_message, 来自SPI控制结构 spi_map_msg, 来自SPI控制结构 transfer_one_message, 来自SPI控制结构 结束 kthread_queue_work yes no

如果SPI任务工作线程忙,则调用kthread_queue_work,将任务工作加入到等待队列。

启动任务工作线程

工作线程(worker)

int kthread_worker_fn(void *worker_ptr)
{struct kthread_worker *worker = worker_ptr;struct kthread_work *work;/** FIXME: Update the check and remove the assignment when all kthread* worker users are created using kthread_create_worker*() functions.*/WARN_ON(worker->task && worker->task != current);worker->task = current;if (worker->flags & KTW_FREEZABLE)set_freezable();repeat:set_current_state(TASK_INTERRUPTIBLE);  /* mb paired w/ kthread_stop */if (kthread_should_stop()) {__set_current_state(TASK_RUNNING);raw_spin_lock_irq(&worker->lock);worker->task = NULL;raw_spin_unlock_irq(&worker->lock);return 0;}work = NULL;raw_spin_lock_irq(&worker->lock);if (!list_empty(&worker->work_list)) {work = list_first_entry(&worker->work_list,struct kthread_work, node);list_del_init(&work->node);}worker->current_work = work;raw_spin_unlock_irq(&worker->lock);if (work) {kthread_work_func_t func = work->func;__set_current_state(TASK_RUNNING);trace_sched_kthread_work_execute_start(work);work->func(work);/** Avoid dereferencing work after this point.  The trace* event only cares about the address.*/trace_sched_kthread_work_execute_end(work, func);} else if (!freezing(current))schedule();try_to_freeze();cond_resched();goto repeat;
}                                                                                                        

这个线程的流程图如下

Created with Raphaël 2.3.0 开始 设置当前任务为可中断 任务工作线程是否应该继续? 从任务链表取下一个任务 有下一个任务工作吗 调用任务工作的回调函数 尝试冻结当前线程 重新规划线程调用 yes no yes no

它检查这个任务线程的任务工作链表,如果非空,那么就从任务工作链表上取下一个任务工作 并运行它的回调函数。这个回调函数在任务工作初始化是设置。
从这个程序段看出,任务工作一定要初始化。

Linux管理线程

Linux系统初始时,产生了一个工作线程的管理线程,这里称其为任务线程产生的监视线程。

kthread_create_worker产生一个struct kthread_create_info变量,并将这个变量加入到一个待产生线程链表中,这个链表的表头是kthread_create_list

监视线程监视这个待产生线程链表,一旦新的变量加入这个链表,这个监视线程就产生一个新的任务工作(worker)线程。

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

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

相关文章

14-44 剑和诗人18 - 你想怎么应用 RAG 与微调

​​​​​​ 要充分发挥 LLM 的潜力,需要在检索增强生成 (RAG) 和微调之间选择正确的技术。 让我们研究一下何时针对 LLM、较小模型和预训练模型使用 RAG 而不是微调。我们将介绍: LLM 和 RAG 的简要背景RAG 相对于微调 LLM 的优势何时针对不同模型大…

AI集成工具平台一站式体验,零门槛使用国内外主流大模型

目录 0 写在前面1 AI艺术大师1.1 绘画制图1.2 智能作曲 2 AI科研助理2.1 学术搜索2.2 自动代码 3 AI智能对话3.1 聊天机器人3.2 模型竞技场 4 特别福利 0 写在前面 人工智能大模型浪潮滚滚,正推动着千行百业的数智化进程。随着技术演进,2024年被视为是大…

linux修改内核实现禁止被ping

概述 Linux默认允许被ping。其主要决定因素为: 内核参数防火墙(iptables/firewall) 以上的决定因素是与的关系,即需要均满足。 因此,修改linux禁被ping有以上两种方法可以实现。 修改内核文件使禁ping 1. 临时生…

服务预约自动化:智能机器人引领预约新潮流

在数字化时代,服务预约的需求日益增长,智能机器人以其自动化和智能化的特性,正在重塑服务预约的流程。 一、服务预约的现代挑战 服务预约流程面临的挑战包括用户操作复杂、等待时间长、个性化服务难以满足等。 二、智能机器人的优势 智能…

Perl 语言入门:编写并执行你的第一个脚本

摘要 Perl 是一种高级、通用的、解释型、动态编程语言,以其强大的文本处理能力而闻名。本文将指导初学者如何编写和执行他们的第一个 Perl 脚本,包括 Perl 的基本概念、脚本的基本结构、运行 Perl 脚本的方法以及一些简单的 Perl 语法。 引言 Perl&am…

保健品商城小程序模板源码

保健品商城小程序模板源码 简洁通用的保健品,健康生活,零售商品,电子商务微信小程序前端模板下载。包含:主页、购物车、客服、个人中心、我的订单、商品详情、我的钱包、设置等等。 保健品商城小程序模板源码

定制化模型炼金术:Mojo模型与自定义训练循环的动态融合

定制化模型炼金术:Mojo模型与自定义训练循环的动态融合 在机器学习领域,模型训练循环是构建智能系统的核心过程。Mojo模型,作为H2O.ai提供的一种模型部署格式,主要用于模型的序列化和预测。虽然Mojo模型本身不支持自定义训练循环…

web安全基础名词概念

本节内容根据小迪安全讲解制作 第一天 域名: 1.1什么是域名? 网域名称(英语:Domain Name,简称:Domain),简称域名、网域,是由一串用点分隔的字符组成的互联网上某一台计算机或计算机组的名称&a…

celery执行任务报错ValueError: not enough values to unpack

背景 在做用户注册模块的时候需要对手机号验证的过程进行优化,目前想到的方式是通过celeryrabbitmq的方式进行异步处理,选择使用celery是因为使用方便、性能好、可分布式部署。 环境信息 目前使用地win11容器化启动 rabbitmq:3.13.2 python:3.6.8 cel…

OEACLE怎么实现AES加密解密

在Oracle数据库中实现AES加密解密,通常会使用Oracle提供的DBMS_CRYPTO包。DBMS_CRYPTO是一个强大的PL/SQL包,用于加密和解密数据,支持多种加密算法,包括AES。以下是实现AES加密解密的具体步骤和示例: 一、确保权限 首…

高薪程序员必修课-JVM创建对象时如何解决多线程内存抢占问题

前言 在JVM中,堆的内存分配过程涉及到线程安全性的保障,具体来说涉及到对象的内存分配时,并不是简单的抢占式分配,而是通过一些机制来保证线程安全和高效的内存管理。下面解释一下JVM是如何设计来保证线程安全的: 内存…

Oracle怎么实现RSA加密解密

Oracle数据库实现RSA加密解密通常需要通过Java编写的存储过程来完成,因为Oracle自身并不直接支持RSA加密的原生函数。以下是实现RSA加密解密的大致步骤和考虑因素: 一、准备Java类 编写Java类: 创建一个Java类(如RSACrypto&…

STA:延迟为什么会有负值?

我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧? 拾陆楼知识星球入口 相关文章链接: STA:串扰延迟分析 STA:CRPR悲观路径移除 这个问题就是典型的SI问题,受SI影响,与hold 分析而言data…

AI Native 入门案例教程

环境准备 1. 安装 AI Native 首先,需要安装 AI Native。可以通过 pip 安装: pip install ainative2. 安装 TensorFlow AI Native 是基于 TensorFlow 的,因此需要安装 TensorFlow。可以通过 pip 安装: pip install tensorflow…

Dify v0.6.9源码部署

一.前置条件 克隆Dify v0.6.9代码: git clone https://github.com/langgenius/dify.git在启用业务服务之前,需要先部署 PostgresSQL / Redis / Weaviate(如果本地没有的话),可以通过以下命令启动: cd do…

Data-Juicer:阿里巴巴荣誉出品的大模型数据清洗框架

Diffusion Models专栏文章汇总:入门与实战 前言:如何优雅地进行大规模数据清洗是一门艺术,特别对于大模型,数据的质量是决定模型成功最关键的因素之一。阿里巴巴最近开源了一项专门针对大语言模型和视频生成大模型的数据清洗框架&…

短信群发平台适用于哪些行业?

短信群发平台作为一种高效、快速且成本相对较低的通信方式,适用于多个行业。以下是一些主要适用行业的概述: 1. 零售与电商行业 应用场景:零售和电商企业可以利用短信群发进行新品推广、促销信息发布、订单状态更新、物流跟踪通知等。 2. 金…

redis并发、穿透、雪崩

Redis如何实现高并发 首先是单线程模型:redis采用单线程可以避免多线程下切换和竞争的开销,提高cpu的利用率,如果是多核cpu,可以部署多个redis实例。基于内存的数据存储:redis将数据存储在内存中,相比于硬…

wireshark抓取Chrome浏览器quic协议的明文包

wireshark版本:Version 4.2.5 (v4.2.5-0-g4aa814ac25a1). 1.chromium浏览器启用quic: chrome://flags/#enable-quic 2.windows添加环境变量 SSLKEYLOGFILED:\sslkeylogfile.log 3.配置wireshark,编辑->首选项->Protocls->TLS:(Pre)-…

MyBatis(30)如何在 MyBatis 中使用 XML 和注解混合配置方式

在MyBatis中,你可以灵活地选择XML配置方式、注解方式,或者将这两种方式混合使用来配置你的映射器(Mapper)。使用混合配置方式,你可以结合两者的优势,例如,利用XML配置复杂查询和动态SQL&#xf…