查询式协作多任务系统

原创 大橙子疯嵌入式 2023-07-10 08:15

点击上方蓝色字体了解更多的嵌入式编程实用技能。
如果你觉得该文章对你有帮助,欢迎点赞+关注

前言

在计算机科学领域,任务调度和协作是关键的概念。虽然传统的操作系统提供了各种任务调度算法和机制,但有时我们需要更灵活、个性化的任务管理方式。

即使采用定时器实现时间片论法任务调度,但是也必须等单个完整的任务执行完成后才能执行下一个完整的任务。

本文将介绍使用标准库头文件中的setjmplongjmp函数构建一个简单的查询式协作多任务系统,无需使用定时器进行任务切换。

setjmplongjmp是C语言标准库头文件中提供的函数。它们的功能是实现非局部跳转,可以在程序的不同位置之间进行跳转,类似于goto语句的扩展。这种非局部跳转的能力为我们构建查询式协作多任务系统提供了基础。

介绍

setjmp和longjmp

setjmp函数用于保存当前程序状态,创建一个可以供后续longjmp函数跳转的上下文环境。在调用setjmp时,程序会记录当前的程序计数器、寄存器和堆栈等状态信息,并将这些信息保存在一个jmp_buf结构中。同时,setjmp函数返回0作为普通调用的返回值,并将jmp_buf作为标识符存储起来。

不同平台的jmp_buf的类型定义不一样,大概占用不到30个字节,因为不同平台的相关寄存器等不一样,因此占用的大小也不同。

longjmp函数则实现了对保存的上下文环境的跳转操作。通过传递之前由setjmp函数保存的jmp_buf标识符,longjmp函数会将程序的状态还原到对应的上下文环境,并且会返回到setjmp处继续执行。

协作式

在协作式多任务调度下,当前任务需要通过主动放弃时间片提供给其他任务运行,而并非是被其他任务抢占,因此这里面并没有所谓的优先级概念之分。

虽然协作式没有所谓的优先级概念之分,但是可以通过一定的方式也能实现一个简单的优先级,比如当前任务主动放弃时间片后,查询更高优先级的任务运行。

时间片论法任务调度只能等任务运行完成才会给下一个任务时间片运行,并不存在主动放弃时间片的功能。

实现思路

了解到setjmplongjmp的功能和原理后,我们能不能通过它们来构建一个任务调度算法和机制呢?
虽然setjmp可以记录当前的程序计数器、寄存器和堆栈等状态信息,但是实现多任务切换时堆栈里面的数据是会发生变化的。

jmp_buf只记录堆栈指针,不记录堆栈指针指向的数据内容。

因此,如果要实现多任务切换,则需要为每个任务分配一定的堆栈预留空间,由于不使用堆,因此可以只考虑栈分配即可。

当前任务主动放弃时间片后,不断查询满足条件需要执行的其他任务。

代码实现

创建任务,使用了setjmp函数。

int cotOs_Creat(OsTask_cb pfnOsTaskEnter, size_t stack)
{
    size_t oldsp;

    if (sg_OsInfo.taskNum >= COT_OS_MAX_TASK || sg_OsInfo.pfnGetTimerMs == NULL)
    {
        return -1;
    }

    COT_OS_GET_STACK(oldsp);
    COT_OS_SET_STACK(sg_OsInfo.stackTop);

    if (0 == setjmp(sg_OsInfo.tcb[sg_OsInfo.taskNum].env))
    {
        COT_OS_SET_STACK(oldsp);
        sg_OsInfo.tcb[sg_OsInfo.taskNum].pfnOsTaskEnter = pfnOsTaskEnter;
        sg_OsInfo.taskNum++;
        sg_OsInfo.stackTop -= stack;
    }
    else
    {
        sg_OsInfo.tcb[sg_OsInfo.taskId].pfnOsTaskEnter();
    }

    return 0;
}

放弃时间片,使用了longjmp,这里集成了时间等待功能,即放弃时间片的时长(即使时长减至0也要等待其他任务主动放弃时间片才会运行)

void cotOs_WaitFor(uint32_t time)
{
    uint32_t timer = sg_OsInfo.pfnGetTimerMs();
    setjmp(sg_OsInfo.tcb[sg_OsInfo.taskId].env);

    if (!(sg_OsInfo.pfnGetTimerMs() - timer > time))
    {
        sg_OsInfo.taskId++;

        if (sg_OsInfo.taskId >= sg_OsInfo.taskNum)
        {
            sg_OsInfo.taskId = 0;
        }

        longjmp(sg_OsInfo.tcb[sg_OsInfo.taskId].env, 1);
    }
}

除了继承时间等待功能外,还定义了一个等待条件的主动放弃放弃时间片功能,即条件不满足时主动放弃时间片(即使条件满足后也要等待其他任务主动放弃时间片才会运行)

#define cotOs_WaitFor_Cond(cond)   do{\
        extern jmp_buf *cotOs_GetTaskEnv1(void);\
        setjmp((*cotOs_GetTaskEnv1()));\
        if (!(cond)){\
            extern void cotOs_RunNextTask(void);\
            cotOs_RunNextTask();\
        }\
    }while (0)

代码链接

目前已完成在STM32板子上的查询式协作多任务系统:
下载链接(点击阅读原文):

https://gitee.com/cot_package/cot_os

扩展

setjmplongjmp除了实现一个多任务系统外,其实还可以有其他的用法,比如实现C++中的try catch抛出异常处理功能。

由于其特性问题,在实际代码中,特别是应用程序代码上,建议少用setjmplongjmp,否则会影响代码阅读,当然,不排除封装成一个特殊的功能外


评论
  • 在智能家居领域中,Wi-Fi、蓝牙、Zigbee、Thread与Z-Wave等无线通信协议是构建短距物联局域网的关键手段,它们常在实际应用中交叉运用,以满足智能家居生态系统多样化的功能需求。然而,这些协议之间并未遵循统一的互通标准,缺乏直接的互操作性,在进行组网时需要引入额外的网关作为“翻译桥梁”,极大地增加了系统的复杂性。 同时,Apple HomeKit、SamSung SmartThings、Amazon Alexa、Google Home等主流智能家居平台为了提升市占率与消费者
    华普微HOPERF 2025-01-06 17:23 145浏览
  • 每日可见的315MHz和433MHz遥控模块,你能分清楚吗?众所周知,一套遥控设备主要由发射部分和接收部分组成,发射器可以将控制者的控制按键经过编码,调制到射频信号上面,然后经天线发射出无线信号。而接收器是将天线接收到的无线信号进行解码,从而得到与控制按键相对应的信号,然后再去控制相应的设备工作。当前,常见的遥控设备主要分为红外遥控与无线电遥控两大类,其主要区别为所采用的载波频率及其应用场景不一致。红外遥控设备所采用的射频信号频率一般为38kHz,通常应用在电视、投影仪等设备中;而无线电遥控设备
    华普微HOPERF 2025-01-06 15:29 129浏览
  • 根据环洋市场咨询(Global Info Research)项目团队最新调研,预计2030年全球无人机锂电池产值达到2457百万美元,2024-2030年期间年复合增长率CAGR为9.6%。 无人机锂电池是无人机动力系统中存储并释放能量的部分。无人机使用的动力电池,大多数是锂聚合物电池,相较其他电池,锂聚合物电池具有较高的能量密度,较长寿命,同时也具有良好的放电特性和安全性。 全球无人机锂电池核心厂商有宁德新能源科技、欣旺达、鹏辉能源、深圳格瑞普和EaglePicher等,前五大厂商占有全球
    GIRtina 2025-01-07 11:02 71浏览
  • 本文介绍Linux系统更换开机logo方法教程,通用RK3566、RK3568、RK3588、RK3576等开发板,触觉智能RK3562开发板演示,搭载4核A53处理器,主频高达2.0GHz;内置独立1Tops算力NPU,可应用于物联网网关、平板电脑、智能家居、教育电子、工业显示与控制等行业。制作图片开机logo图片制作注意事项(1)图片必须为bmp格式;(2)图片大小不能大于4MB;(3)BMP位深最大是32,建议设置为8;(4)图片名称为logo.bmp和logo_kernel.bmp;开机
    Industio_触觉智能 2025-01-06 10:43 87浏览
  • 大模型的赋能是指利用大型机器学习模型(如深度学习模型)来增强或改进各种应用和服务。这种技术在许多领域都显示出了巨大的潜力,包括但不限于以下几个方面: 1. 企业服务:大模型可以用于构建智能客服系统、知识库问答系统等,提升企业的服务质量和运营效率。 2. 教育服务:在教育领域,大模型被应用于个性化学习、智能辅导、作业批改等,帮助教师减轻工作负担,提高教学质量。 3. 工业智能化:大模型有助于解决工业领域的复杂性和不确定性问题,尽管在认知能力方面尚未完全具备专家级的复杂决策能力。 4. 消费
    丙丁先生 2025-01-07 09:25 80浏览
  • 村田是目前全球量产硅电容的领先企业,其在2016年收购了法国IPDiA头部硅电容器公司,并于2023年6月宣布投资约100亿日元将硅电容产能提升两倍。以下内容主要来自村田官网信息整理,村田高密度硅电容器采用半导体MOS工艺开发,并使用3D结构来大幅增加电极表面,因此在给定的占位面积内增加了静电容量。村田的硅技术以嵌入非结晶基板的单片结构为基础(单层MIM和多层MIM—MIM是指金属 / 绝缘体/ 金属) 村田硅电容采用先进3D拓扑结构在100um内,使开发的有效静电容量面积相当于80个
    知白 2025-01-07 15:02 75浏览
  • 根据Global Info Research项目团队最新调研,预计2030年全球封闭式电机产值达到1425百万美元,2024-2030年期间年复合增长率CAGR为3.4%。 封闭式电机是一种电动机,其外壳设计为密闭结构,通常用于要求较高的防护等级的应用场合。封闭式电机可以有效防止外部灰尘、水分和其他污染物进入内部,从而保护电机的内部组件,延长其使用寿命。 环洋市场咨询机构出版的调研分析报告【全球封闭式电机行业总体规模、主要厂商及IPO上市调研报告,2025-2031】研究全球封闭式电机总体规
    GIRtina 2025-01-06 11:10 104浏览
  • 这篇内容主要讨论三个基本问题,硅电容是什么,为什么要使用硅电容,如何正确使用硅电容?1.  硅电容是什么首先我们需要了解电容是什么?物理学上电容的概念指的是给定电位差下自由电荷的储藏量,记为C,单位是F,指的是容纳电荷的能力,C=εS/d=ε0εrS/4πkd(真空)=Q/U。百度百科上电容器的概念指的是两个相互靠近的导体,中间夹一层不导电的绝缘介质。通过观察电容本身的定义公式中可以看到,在各个变量中比较能够改变的就是εr,S和d,也就是介质的介电常数,金属板有效相对面积以及距离。当前
    知白 2025-01-06 12:04 173浏览
  • 彼得·德鲁克被誉为“现代管理学之父”,他的管理思想影响了无数企业和管理者。然而,关于他的书籍分类,一种流行的说法令人感到困惑:德鲁克一生写了39本书,其中15本是关于管理的,而其中“专门写工商企业或为企业管理者写的”只有两本——《为成果而管理》和《创新与企业家精神》。这样的表述广为流传,但深入探讨后却发现并不完全准确。让我们一起重新审视这一说法,解析其中的矛盾与根源,进而重新认识德鲁克的管理思想及其著作的真正价值。从《创新与企业家精神》看德鲁克的视角《创新与企业家精神》通常被认为是一本专为企业管
    优思学院 2025-01-06 12:03 119浏览
  • By Toradex 秦海1). 简介嵌入式平台设备基于Yocto Linux 在开发后期量产前期,为了安全以及提高启动速度等考虑,希望将 ARM 处理器平台的 Debug Console 输出关闭,本文就基于 NXP i.MX8MP ARM 处理器平台来演示相关流程。 本文所示例的平台来自于 Toradex Verdin i.MX8MP 嵌入式平台。  2. 准备a). Verdin i.MX8MP ARM核心版配合Dahlia载板并
    hai.qin_651820742 2025-01-07 14:52 48浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦