任务调度器

任务调度器详解(FreeRTOS) 任务调度器是实时操作系统(RTOS)的一个关键组件,它负责决定在多个可运行任务中哪一个将获得CPU时间以执行。它基于任务的优先级和状态来做出这些决定。在一个RTOS中,可能会有多个任务同时运行,但是在任意时刻,CPU只能执行一个任务。任务调度器的主要目标是按照系统的需求合理分配CPU时间。基本功能任务的选择:任务调度器会根据预设的算法从所有可运行的任务中选择一个要执行的任务。任务的优先级:任务通常会被分配一个优先级,优先级越高的任务在抢占式调度中会优先执行。任务状态管理。 阅读详情

比特币源码分析:任务调度器的使


5359


 

任务调度器

 

Bitcoin 进程启动后,有一个专门的线程做任务调度, 这些任务根据指定的时刻,执行对应的函数:

bool AppInitMain()
 {
 .......
 // Start the lightweight task scheduler thread
 CScheduler::Function serviceLoop = boost::bind(&CScheduler::serviceQueue, &scheduler);
 threadGroup.create_thread(boost::bind(&TraceThread, "scheduler", serviceLoop));
 .......
 }

调度器类主要是实现了一个生产者消费者的任务队列,只是这个任务队列是用 std::multimap 实现的,map 的key表达某一时刻,map的值表达:那一时刻要执行的函数,内部使用条件变量和锁来保护multimap ,还有几个bool 条件:

class CScheduler
 {
 public:
 CScheduler();
 ~CScheduler();
 typedef std::function<void(void)> Function;
 void schedule(Function f, boost::chrono::system_clock::time_point t=boost::chrono::system_clock::now());
 void scheduleFromNow(Function f, int64_t deltaMilliSeconds);
 void scheduleEvery(Function f, int64_t deltaMilliSeconds);
 void serviceQueue();
 void stop(bool drain=false);
 size_t getQueueInfo(boost::chrono::system_clock::time_point &first,
 boost::chrono::system_clock::time_point &last) const;
 bool AreThreadsServicingQueue() const;
 private:
 std::multimap<boost::chrono::system_clock::time_point, Function> taskQueue;
 boost::condition_variable newTaskScheduled;
 mutable boost::mutex newTaskMutex;
 int nThreadsServicingQueue;
 bool stopRequested;
 bool stopWhenEmpty;
 bool shouldStop() const { return stopRequested || (stopWhenEmpty && taskQueue.empty()); }
 };

CScheduler的client 通过调用schedule 往内部multimap添加一个条目; scheduleFromNow 和scheduleEvery 内部都是调用schedule 方法实现; 这三个方法属于生产者要生产任务的方法, 任务的消费者调用serviceQueue等待取走任务, 然后执行。

目前整个程序有一个全局的CScheduler实例:

static CScheduler scheduler; 这个实例对应只有一个消费者线程, 即唯一的后台调度器线程。

class SingleThreadedSchedulerClient 主要用途是,借助CScheduler类型,保障被添加到内部链表的任务,被串行执行:

class SingleThreadedSchedulerClient {
 private:
 CScheduler *m_pscheduler;
 CCriticalSection m_cs_callbacks_pending;
 std::list<std::function> m_callbacks_pending;
 bool m_are_callbacks_running = false;
 void MaybeScheduleProcessQueue();
 void ProcessQueue();
 public:
 explicit SingleThreadedSchedulerClient(CScheduler *pschedulerIn) : m_pscheduler(pschedulerIn) {}
 void AddToProcessQueue(std::function func);
 void EmptyQueue();
 size_t CallbacksPending();
 };

 

使用例子

 

基本的使用例子:

#include
 #include <boost/bind.hpp>
 #include <boost/thread.hpp>
 #include <boost/test/unit_test.hpp>
 #include
 static void doN(){
 std::cout << "output now\n";
 }
 static void doE(){
 for(int i = 0; i < 10; i++){
 std::cout << "i = " << i << '\n';
 }
 std::cout << '\n';
 }
 BOOST_AUTO_TEST_SUITE(sche_tests)
 BOOST_AUTO_TEST_CASE(sche)
 {
 CScheduler s;
 s.scheduleFromNow(doN, 1000);
 s.scheduleEvery(doE, 1000);
 boost::thread t(boost::bind(&CScheduler::serviceQueue, &s));
 boost::this_thread::sleep_for(boost::chrono::seconds{5});
 t.interrupt();
 t.join();
 }
 BOOST_AUTO_TEST_CASE(singlethread)
 {
 CScheduler s;
 SingleThreadedSchedulerClient sc (&s);
 for(int i = 1; i <11; i++){
 auto f = [=]{
 std::cout << "thread " << boost::this_thread::get_id() << " print arg: " << i << '\n'; }; sc.AddToProcessQueue(f); } boost::thread t(boost::bind(&CScheduler::serviceQueue, &s)); boost::this_thread::sleep_for(boost::chrono::seconds{1}); t.interrupt(); t.join(); } BOOST_AUTO_TEST_SUITE_END()

进程启动后, 全局对象连接管理器connman初始化后, connman 的Start 方法最后,通过scheduler 线程安排了一个定时任务: 每隔15分钟, 把connman 对象内部成员,banmap_t 类型的 setBanned, CAddrMan 类型的addrman 序列化到本地文件banlist.dat 和 peers.dat。

//init.cpp if (!connman.Start(scheduler, connOptions)) { return false; } //net.cpp bool CConnman::Start(CScheduler& scheduler, const Options& connOptions) { ............... scheduler.scheduleEvery(std::bind(&CConnman::DumpData, this), DUMP_ADDRESSES_INTERVAL * 1000); }

如果钱包功能编译使能, 会让scheduler 线程安排每隔500毫秒刷新钱包状态。

//init.cpp #ifdef ENABLE_WALLET StartWallets(scheduler); #endif //wallet/init.cpp void StartWallets(CScheduler& scheduler) { for (CWalletRef pwallet : vpwallets) { pwallet->postInitProcess(scheduler);
 }
 }
 //wallet/wallet.cpp
 void CWallet::postInitProcess(CScheduler& scheduler)
 {
 ReacceptWalletTransactions();
 if (!CWallet::fFlushScheduled.exchange(true)) {
 scheduler.scheduleEvery(MaybeCompactWalletDB, 500);
 }
 }

PeerLogicValidation 对象的构造函数内部, scheduler 线程安排每45秒执行CheckForStaleTipAndEvictPeer函数主要做两件事:

  1. 关掉多余的外出tcp 连接
  2. 根据当前时间,检查当前节点的blockchain 的tip 是否有可能过时了,建立额外的连接同步跟上
PeerLogicValidation::PeerLogicValidation(CConnman* connmanIn, CScheduler &scheduler) : connman(connmanIn), m_stale_tip_check_time(0) {
 // Initialize global variables that cannot be constructed at startup.
 recentRejects.reset(new CRollingBloomFilter(120000, 0.000001));
 const Consensus::Params& consensusParams = Params().GetConsensus();
 // Stale tip checking and peer eviction are on two different timers, but we
 // don't want them to get out of sync due to drift in the scheduler, so we
 // combine them in one function and schedule at the quicker (peer-eviction)
 // timer.
 static_assert(EXTRA_PEER_CHECK_INTERVAL < STALE_CHECK_INTERVAL, "peer eviction timer should be less than stale tip check timer"); scheduler.scheduleEvery(std::bind(&PeerLogicValidation::CheckForStaleTipAndEvictPeers, this, consensusParams), EXTRA_PEER_CHECK_INTERVAL * 1000); } void PeerLogicValidation::CheckForStaleTipAndEvictPeers(const Consensus::Params &consensusParams) { if (connman == nullptr) return; int64_t time_in_seconds = GetTime(); EvictExtraOutboundPeers(time_in_seconds); if (time_in_seconds > m_stale_tip_check_time) {
 LOCK(cs_main);
 // Check whether our tip is stale, and if so, allow using an extra
 // outbound peer
 if (TipMayBeStale(consensusParams)) {
 LogPrintf("Potential stale tip detected, will try using extra outbound peer (last tip update: %d seconds ago)\n", time_in_seconds - g_last_tip_update);
 connman->SetTryNewOutboundPeer(true);
 } else if (connman->GetTryNewOutboundPeer()) {
 connman->SetTryNewOutboundPeer(false);
 }
 m_stale_tip_check_time = time_in_seconds + STALE_CHECK_INTERVAL;
 }
 }

以上就是bitoin 里面CScheduler类的主要使用场景。

基于单片机的简单的任务调度器 近来工作之余,研究了一下APM的源码。 APM源码连接https://pan.baidu.com/s/17Dg1oEJT_fj12DM1BmZWxA 发现源码中有一个简单的任务调度器,不太重要的任务都在Scheduler中完成。为什么需要Scheduler呢?? 飞行器姿态信息需要角速度积分,位置信息也需要光流的积分,也就是需要获取精确的时间间隔,对时间敏感。 Scheduler的主要作用是保证主函数运行的时间相同,什么原理呢? 假设我们主循环中有6个任务, 每个任务执行时间为1ms,而我们的控制周期要求 阅读详情

相关推荐

第二讲:任务调度器

第二讲:任务调度器

2301_81039760的博客 1120

bitcoin task scheduler 使用

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34255793的博客 254

思岚A1 上手教程

前言 寒假在家闲着也是闲着,索性就向是实验室借了一个思岚 A1激光雷达,来进一步完成自己的实验室实习项目。经过一个月在Linux上和ROS上的摸爬滚打,我已经对机器人开发和SLAM有了初步了解,现在就写个上手教程吧(以防自己以后忘了)。 Basic Support 硬件 一台电脑 思岚 A1激光雷达 软件 安装Virtual Box虚拟机 在虚拟机安装Ubuntu 16操作系统 在Ubuntu 16搭建ROS kinetic 简要步骤 1.现在w..

ajxdhe的博客 6384

力扣621.任务调度器

任务调度器 给你一个用字符数组tasks 表示的 CPU 需要执行的任务列表。其中每个字母表示一种不同种类的任务。任务可以以任意顺序执行,并且每个任务都可以在 1 个单位时间内执行完。在任何一个单位时间,CPU 可以完成一个任务,或者处于待命状态。 然而,两个 相同种类 的任务之间必须有长度为整数 n 的冷却时间,因此至少有连续 n 个单位时间内 CPU 在执行不同的任务,或者在待命状态。 你需要计算完成所有任务所需要的 最短时间 。 示例 1: 输入:tasks = ["A","...

我就吃一口的BLOG 693

数据结构与算法 —— 最短路径Dijkstra算法(迪杰斯特拉)详细图解以及python实现

前两章我们讲到了关于图的基本知识,和广度/深度优先搜索。本章,我们将介绍加权图和最短路径的相关知识。最短路径和最小生成树是图论中常见的问题。最短路径是指在一个图中找到两个节点之间的最短路径,最小生成树是指在一个图中找到一个连通子图,使得所有节点都能够互相到达,且总权值最小。最短路径算法常见的有floyd算法(弗洛伊德算法)和 dijkstra算法(迪杰斯特拉)。本文只介绍dijkstra算法。最短路径运用非常广泛,比如在导航系统中,确定两个地点间哪条路线最短;

‘’ 2万+

四款办公Agent实测对比:WorkBuddy、千问办公、库库AI、豆包工作怎么选

AI Agent是一种能感知环境、自主决策并执行动作的智能系统,其核心在于工具调用、状态管理与错误恢复构成的执行闭环。在办公场景中,任务边界清晰、容错率高、重复性强,使Agent成为最容易落地的方向。通过调用本地文件、脚本或办公套件,Agent能自动完成文件批量处理、文档摘要、会议纪要等重复劳动,显著提升工作效率。目前WorkBuddy、千问办公、库库AI、豆包工作等产品分别从本地操作、办公套件嵌入、知识处理、轻量助手等路线切入,用户可根据自身场景选择。

weixin_29052717的博客 521

leetcode:621. 任务调度器

因为相同任务必须要有时间片为n的间隔,所以我们先把出现次数最多的任务A安排上(当然也可以选择任务B)。例子中n=2,那么任意两个任务A之间都必须间隔2个单位的时间。中间间隔的单位时间可以用来安排别的任务,也可以出于“待命”状态。当然,为了使得总任务时间最短,我们要尽可能的把单位时间分配个其他任务。此时如果按照上述方法计算将得到结果为 8,比数组总长度 10 要小,应返回数组长度。为什么是数组长度呢?很容易观察到,前面两个A任务一定会固定跟着2个单位时间的间隔。完成所有任务的最短时间取决于。

OceanStar的博客 637

实战复盘:如何用ATE(自动测试设备)搞定一颗MCU的功能测试全流程

本文详细解析了如何利用ATE(自动测试设备)完成MCU功能测试的全流程,涵盖测试需求分析、测试向量生成、ATE测试程序开发及调试实战。通过真实案例分享,帮助工程师高效解决芯片测试中的常见问题,提升Functional Test的准确性和效率。

weixin_30872157的博客 485

LeetCode621:任务调度器

给你一个用字符数组 tasks 表示的 CPU 需要执行的任务列表。其中每个字母表示一种不同种类的任务。任务可以以任意顺序执行,并且每个任务都可以在 1 个单位时间内执行完。在任何一个单位时间,CPU 可以完成一个任务,或者处于待命状态。然而,两个 相同种类 的任务之间必须有长度为整数 n 的冷却时间,因此至少有连续 n 个单位时间内 CPU 在执行不同的任务,或者在待命状态。你需要计算完成所有任务所需要的 最短时间。

46426906的博客 438

PINN内嵌物理知识神经网络入门及文献总结

内嵌物理知识深度学习方法(PINN)已经成功用于解决各类科学计算问题,其本质是将物理先验知识嵌入神经网络训练中,将一个求解PDE的问题转化为一个优化问题。这篇博客主要记录PINN相关论文

山里娃的博客 7万+

【YOLO11改进 - 注意力机制】SCSA通过结合空间注意力和通道注意力,提高各种下游视觉任务的性能。

【YOLO11改进 - 注意力机制】SCSA通过结合空间注意力和通道注意力,提高各种下游视觉任务的性能。

专注于图像领域,主要研究内容包括计算机视觉和深度学习,特别是在图像分类、目标检测和图像生成等方面有深入的研究和实践经验。 474

12-海豚调度器DolphinScheduler

自定义日期格式$[yyyyMMdd]也可以写成$[yyyy-MM-dd]$[HHmmss] 也可以添加: $[HH:mm:ss]

qq_43819048的博客 6156

(王道408考研数据结构)第二章线性表-第一节:线性表的定义和基本操作

文章目录一:线性表的定义二:线性表的基本操作 一:线性表的定义 线性表(Linear List):零个或多个数据元素的有限序列 元素之间是有顺序的 若元素存在多个,则第一个元素无前驱,最后一个元素无后继,其他元素都有且只有一个前驱和后继 线性表强调有限,“所有的整数按递增次序排列”很明显不是线性表 线性表可以表示为 L=(a1,a1,...,ai+1,...,an)L=(a_{1},a_{1},...,a_{i+1},...,a_{n})L=(a1​,a1​,...,ai+1​,...,an​) a

快乐江湖的博客 3704

关于任务调度器的感悟

今天我们重点介绍裸机任务调度器。所谓裸机任务调度器,是指在裸机编程环境下实现的任务管理机制。裸机编程指的是直接基于硬件平台进行开发,无需操作系统支持,由程序直接掌控CPU、内存和外设等硬件资源。这个调度器相当于一个智能的时间管家,它能统筹管理项目中各类周期性任务的执行时序,比如LED闪烁控制、按键检测等常见功能。下面我将分享初学阶段遇到的几个典型问题,看看大家是否也有类似的困惑。答:回答这个问题之前,我们要先了解一下任务调度器的作用是什么?能实现什么功能?

2401_84570057的博客 1133

客服转人工率直降60%!OpenClaw深度集成NLP引擎,打造企业级对话自动化智能客服系统

本文介绍了一套基于OpenClaw智能体框架和NLP大模型引擎的智能客服系统解决方案。该系统通过深度集成NLP引擎实现精准语义理解,采用分层架构设计支持多渠道接入和业务系统对接,显著提升了客服效率。核心亮点包括:92%的重复问题自动解决率,60%的转人工率下降,40%的人力成本降低,以及从30秒压缩至0.5秒的平均响应时长。文章详细阐述了技术选型、系统架构设计、核心模块实现等关键环节,展示了如何通过智能对话系统破解传统客服业务中的人力资源与服务质量矛盾。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 361

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

FreeRTOS-实现任务调度器

本文正式开启对FreeRTOS内核的研究,首当其冲的就是就是任务调度器的实现,任务调度器作为FreeRTOS的核心,因为FreeRTOS的本质就是任务的轮流运行,为了循序渐进的学习,避免一口吃成一个大胖子,本文只实现两个任务的切换,先不管任务的优先级,本文的目的就是将任务切换的全过程分析的透透彻彻,在此之前要深入理解FreeRTOS链表操作,还有ARM架构的知识,我已经帮你们总结好了。《FreeRTOS-链表的源码解析》《FreeRTOS-ARM架构与程序的本质》《FreeRTOS-ARM架构深入理解》

k666499436的博客 1万+

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

rtos05:任务调度器和中断

抢占优先级一致时,若子优先级高,不会发生打断,只会优先级排序最高。5-15的均可以,0-4的无法被rtos管理。

2301_80026293的博客 2066

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

RTOS之UCOS(二)---任务调度器

一、什么是任务调度器 1.1 多任务并行机制 对很多人来说,多任务并行机制挺神秘的,甚至对很多有多线程并发编程经验的工程师来说也是如此。前面我用五篇文章谈了C++多线程并发编程的原理与技巧,但对操作系统的多任务并行机制并没有过多阐述。现在回顾下从单任务顺序执行到多任务并行执行的演变过程,有利于打破多任务并行机制的神秘感。 多任务并行机制从技术上来说就是程序流折断 + 现场(在操作系统里叫上下文)保...

流云 3724

FreeRTOS启动任务调度器

这部分内容就要去深入了解源码以及熟悉汇编语言的操作。依旧正点原子的视频。

qq_44219883的博客 1019

FreeRTOS——任务调度器+任务切换

介绍了有关FreeRTOS任务调度器的启动和任务切换

2301_76901677的博客 1618

621. 任务调度器

题目: 621. 任务调度器 题解: 代码: import java.util.Arrays; public class code621 { public static int leastInterval(char[] tasks, int n) { int count[] = new int[26]; // 统计词频 for(int i = 0; i < tasks.length; i++) {

dev_zyx的博客 524

力扣: 任务调度器

题目描述 给你一个用字符数组 tasks 表示的 CPU 需要执行的任务列表。其中每个字母表示一种不同种类的任务。任务可以以任意顺序执行,并且每个任务都可以在 1 个单位时间内执行完。在任何一个单位时间,CPU 可以完成一个任务,或者处于待命状态。 然而,两个 相同种类 的任务之间必须有长度为整数 n 的冷却时间,因此至少有连续 n 个单位时间内 CPU 在执行不同的任务,或者在待命状态。 你需要计算完成所有任务所需要的 最短时间 。 力扣:621.任务调度器 输入:tasks = [“A”,“A”,“

ZhangyiA的博客 571

leetcode621:任务调度器

leetcode621:任务调度器先看问题:解答思路代码:提交结果 先看问题: 给定一个用字符数组表示的 CPU 需要执行的任务列表。其中包含使用大写的 A - Z 字母表示的26 种不同种类的任务。任务可以以任意顺序执行,并且每个任务都可以在 1 个单位时间内执行完。CPU 在任何一个单位时间内都可以执行一个任务,或者在待命状态。 然而,两个相同种类的任务之间必须有长度为 n 的冷却时间,因此至...

luckytsw的博客 2496

解释 C# 中使⽤任务调度器实现并⾏编程的原理

任务调度器是 C# 并行编程的重要组成部分,它通过管理任务的执行顺序和线程分配,提升了程序的性能和资源利用率。默认任务调度器基于线程池实现,提供了良好的通用性能,而自定义任务调度器则允许开发者根据具体需求调整调度策略,从而在特定场景中优化任务执行。是任务并行库(Task Parallel Library, TPL)的核心组件之一。它负责管理和调度任务的执行,通过优化线程的分配和任务的执行顺序来提升程序的性能。),它定义了如何管理任务的执行。默认情况下,C# 中的任务调度器使用 .NET 框架的线程池 (

fapw15的博客 694
上一篇: block header
下一篇: boost::signal
TuxedoLinux
博客等级 码龄9年 268粉丝 34原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值