返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >怎么用C语言实现任务调度
  • 188
分享到

怎么用C语言实现任务调度

2023-07-05 23:07:22 188人浏览 泡泡鱼
摘要

这篇文章主要介绍“怎么用C语言实现任务调度”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“怎么用C语言实现任务调度”文章能帮助大家解决问题。任务调度模式结构整体上的结构属于线性结构,结合链表和定时器来

这篇文章主要介绍“怎么用C语言实现任务调度”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“怎么用C语言实现任务调度”文章能帮助大家解决问题。

任务调度模式结构

整体上的结构属于线性结构,结合链表和定时器来实现,我使用的是sysTick这个滴答时钟,1ms的频率,功能比较简单,容易理解。

分片

分片的模式,主要体现在函数分片和时间分片在我之前就有使用在函数中,主要的思路是,把函数功能切片,分为几个小部分,每次执行时按次序执行小部分,对于没有时序要求的函数来说,可以把一个占用CPU大的功能分摊开来实现,从而避免有些地方耗时长的问题。对于时间分片,其实就是定时器的一种应用,实际上,函数分片在执行的时候已经是一种时间分片了,不过现在加上人为的控制在里面了。

下面是函数分片的一般结构:

void func(char *fos,...){    static char step=0;//顺序控制变量,自由度比较高,可乱序,可循环,可延迟执行    switch(step){        case 0:{            //...            step++;            break;        }        case 1:{            //...            step++;            break;        }        //...        default:{            //step++;//可以借助default实现延时的效果,即跳过几次空白step            break;        }    }    return;}

其中添加的参数变量*fos必要的,因为就是通过传入每个任务的这个标志位来判断是否运行结束,而其他的参数,就得基于具体任务做不一样的处理了。

轮询

运行框图

怎么用C语言实现任务调度

可以看到这个框图是一个头尾相连的闭环结构,从头节点依次运行到尾节点后再从头循环往复执行下去。

轮询函数

void loop_task(void){static Task_Obj *tasknode;tasknode=task_curnode->next;//repoint the curnode to the nextif(tasknode==NULL){//tasknode is null,only the headnode have the attrreturn;//express the task space is none}else if(tasknode->task_type==TYPE_HEAD){//tasknode is headnodetask_curnode=tasknode;return;}else{if(tasknode->run_type == RUN_WaiT){            //等待型任务,通过ready标志来确定是否执行,否则就跳过if(!tasknode->ready){if(task_curnode->next !=NULL){task_curnode=task_curnode->next;return;}}}if(tasknode->task_status==STATUS_INIT){tasknode->tickstart=HAL_GetTick();//获取ticktasknode->task_status=STATUS_RUN;}else if(tasknode->task_status==STATUS_RUN){if((HAL_GetTick() - tasknode->tickstart) > (uint32_t)tasknode->task_tick){tasknode->task_name(&(tasknode->task_fos));//run the step task,transfer the fostasknode->tickstart+=(uint32_t)tasknode->task_tick;//update the tickstart}}}if(tasknode->task_fos==FOS_FLAG){tasknode->ready=0;if(tasknode->waittask!=NULL){            //置位该任务绑定的等待的任务准备运行标志位,标识可以准备运行了tasknode->waittask->ready=1;}        //运行结束就删掉该任务delete_task(tasknode);}else if(tasknode->task_fos==FOC_FLAG){        //循环运行该任务tasknode->task_status=STATUS_INIT;//continue running from starttasknode->task_fos=0;//RESET fos}if(task_curnode->next !=NULL){if(task_curnode->next->run_type==RUN_FORCE) return;//force-type's taskelse task_curnode=task_curnode->next;}}

其中有几个运行态和标志位

#define FOS_FLAG 99//运行结束标志#define FOC_FLAG 100//运行结束后再次执行,相当于循环运行#define TYPE_NOMAL 0//标识一般任务类型#define TYPE_HEAD 1//标识头任务类型#define TYPE_END 2//标识尾任务类型#define RUN_NORMAL 0//一般轮询模式#define RUN_FORCE 1//强制运行该任务,运行结束才继续下一个任务#define RUN_WAIT 2//等待指定的任务结束,才可以被运行#define STATUS_INIT 0//任务的准备阶段,用于获取起始时间#define STATUS_RUN 1//任务运行阶段#define STATUS_UNVAILED 2//无效状态

运行时对时间间隔tick的把握还有点问题,这个等待后面有机会优化下。

调度实现

任务链表结构

typedef struct TASK_CLASS{void (*task_name)(char *taskfos,...);//任务函数int task_tick;//任务的时间分片间隔uint32_t tickstart;//起始时间点,每次执行完须加上一个tickchar task_fos;//运行结束标志char task_type;//任务类型变量char task_status;//任务状态char run_type;//运行状态char ready;//准备运行标志位struct TASK_CLASS *next;//下一任务struct TASK_CLASS *waittask;//等待执行的任务} Task_Obj;

添加任务

add_task

void add_task(void (*taskname)(char *,...),int tasktick,int runtype){//可变参,这里未做处理Task_Obj *tasknode,*tmpnode;char i;tasknode = (Task_Obj*)malloc(sizeof(Task_Obj));tasknode->task_name=taskname;tasknode->task_tick=tasktick;tasknode->task_fos=0;tasknode->task_status=STATUS_INIT;//initial statustasknode->task_type=TYPE_END; //set the new node to endnodetasknode->run_type=runtype;tasknode->next=&task_headnode;//the endnode point to the headnodetmpnode=&task_headnode;if(task_num==0){tmpnode->next=tasknode;task_num++;return;}for(i=0;i<task_num;i++){tmpnode=tmpnode->next;//reach the endnode}tmpnode->task_type=TYPE_NOMAL;//turn the last endnode to the normal nodetmpnode->next=tasknode;task_num++;}

add_wait_task

void add_wait_task(void (*taskname)(char *),void (*waitname)(char *),int tasktick){Task_Obj *tmpnode,*tasknode;char i,pos;tmpnode=&task_headnode;for(i=0;i<task_num;i++){tmpnode=tmpnode->next;//reach the endnodeif(tmpnode->task_name==taskname){pos=i;//获取要等待任务的位置break;}}tasknode = (Task_Obj*)malloc(sizeof(Task_Obj));tasknode->task_name=waitname;tasknode->task_tick=tasktick;tasknode->task_fos=0;tasknode->task_status=STATUS_INIT;//initial statustasknode->task_type=TYPE_END; //set the new node to endnodetasknode->run_type=RUN_WAIT;//任务为等待运行tasknode->ready=0;tasknode->next=&task_headnode;//the endnode point to the headnodetmpnode->waittask=tasknode;//获取新建的等待执行的任务地址,在运行结束后把等待执行的任务的准备运行标志位置1tmpnode=&task_headnode;if(task_num==0){tmpnode->next=tasknode;task_num++;return;}for(i=0;i<task_num;i++){tmpnode=tmpnode->next;//reach the endnode}tmpnode->task_type=TYPE_NOMAL;//turn the last endnode to the normal nodetmpnode->next=tasknode;task_num++;}

删除任务

delete_task(局限性大,只针对当前运行的任务而言)

void delete_task(Task_Obj *taskobj){if(task_curnode->task_type==TYPE_HEAD && task_num < 2){//if curnode is headnode,and tasknum=1task_curnode->next=NULL;}else{task_curnode->next=taskobj->next;//repoint the curnode next}free(taskobj);//free the space of where the taskobj pointedtask_num--;}

delete_task_withname(删除指定任务名的任务)

void delete_task_withname(void (*taskname)(char *)){Task_Obj *tmpnode,*tmpnode2;char i,pos;tmpnode=&task_headnode;for(i=0;i<task_num;i++){tmpnode=tmpnode->next;//reach the endnodeif(tmpnode->task_name==taskname){pos=i;break;}}if(i==task_num) return;tmpnode=&task_headnode;for(i=0;i<pos+1;i++){tmpnode2=tmpnode;tmpnode=tmpnode->next;}if(tmpnode->next==NULL){//if tmpnode is endnodetmpnode2->next=&task_headnode;}else{tmpnode2->next=tmpnode->next;//repoint the curnode next}task_num--;free(tmpnode);}

初始化任务空间

void non_task(char *taskfos){return;}void init_taskspace(void){task_headnode.task_name=non_task;task_headnode.task_type=TYPE_HEAD;task_headnode.task_status=STATUS_UNVAILED;task_headnode.next=NULL;task_curnode=&task_headnode;//头节点是没有任务需要执行的task_num=0;}

调用实例

add_task(task1,500,RUN_NORMAL);//500ms执行一次task1任务add_wait_task(task1,task2,500);//task2等待task1结束才会执行,运行的时间间隔为500msdelete_task_withname(task1);//删除task1任务while(1){    //...    loop_task();//任务轮询}

关于“怎么用C语言实现任务调度”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注编程网其他教程频道,小编每天都会为大家更新不同的知识点。

--结束END--

本文标题: 怎么用C语言实现任务调度

本文链接: https://lsjlt.com/news/356300.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 怎么用C语言实现任务调度
    这篇文章主要介绍“怎么用C语言实现任务调度”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“怎么用C语言实现任务调度”文章能帮助大家解决问题。任务调度模式结构整体上的结构属于线性结构,结合链表和定时器来...
    99+
    2023-07-05
  • 利用C语言实现任务调度的示例代码
    目录前言任务调度模式结构分片轮询调度实现结语前言 这个任务调度模块的实现是形成于毕设项目中的,用在STM32中,断断续续跨度2个月实现了一些基本功能,可能后面再做其他项目时会一点点完...
    99+
    2023-05-15
    C语言实现任务调度 C语言任务调度
  • quartz任务调度怎么实现
    在Java中,可以使用Quartz任务调度框架来实现任务调度。以下是实现Quartz任务调度的一般步骤:1. 添加依赖:在项目的构建...
    99+
    2023-08-31
    quartz
  • springboot任务调度怎么实现
    要在Spring Boot中实现任务调度,可以使用Spring Task框架。下面是一些步骤来实现任务调度:1. 在pom.xml文...
    99+
    2023-10-11
    springboot
  • C# TaskScheduler任务调度器的实现
    目录什么是TaskScheduler?TaskScheduler  任务调度器的原理 .net中的任务调度器有哪些一: ThreadPoolTaskSc...
    99+
    2023-05-20
    C# TaskScheduler任务调度器 C# TaskScheduler
  • java任务调度quartz怎么实现
    使用Quartz实现Java任务调度的步骤如下:1. 导入Quartz库:在项目的依赖管理中,添加Quartz库的Maven或Gra...
    99+
    2023-09-18
    quartz java
  • 怎么用C语言递归实现火车调度算法
    这篇文章主要介绍怎么用C语言递归实现火车调度算法,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1、代码题目如下:2.8编号为1,2,3,4的四列火车通过一个栈式的列车调度站,可能得到的调度结果有哪些?如果有n列火车通...
    99+
    2023-06-25
  • Go语言dolphinscheduler任务调度处理
    目录简介自动化使用例子任务结果检查测试连接重跑任务小结简介 dolphinscheduler是一个可视化DAG工作流任务调度平台,在大数据领域做任务调用非常流行 提供了类似a...
    99+
    2022-06-08
    GO
  • golang任务调度框架怎么实现
    要实现一个Golang任务调度框架,可以按照以下步骤进行: 定义任务结构体:首先,定义一个任务结构体,包含任务的属性,例如任务的I...
    99+
    2023-10-25
    golang
  • 利用Go语言快速实现一个极简任务调度系统
    目录引子思路实战交互界面定时任务任务执行代码效果总结引子 任务调度(Task Scheduling)是很多软件系统中的重要组成部分,字面上的意思是按照一定要求分配运行一些通常时间较长...
    99+
    2024-04-02
  • java分布式任务调度怎么实现
    实现Java分布式任务调度可以使用以下方法:1. 使用Quartz:Quartz是一个功能强大的开源任务调度框架,可以在Java应用...
    99+
    2023-10-23
    java
  • Laravel怎么实现队列和任务调度
    本文小编为大家详细介绍“Laravel怎么实现队列和任务调度”,内容详细,步骤清晰,细节处理妥当,希望这篇“Laravel怎么实现队列和任务调度”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。一、 我们首先准备一下...
    99+
    2023-07-04
  • go语言怎么调用c语言
    Go语言可以通过使用cgo工具以及一些特定的语法来调用C语言代码。 以下是调用C语言的Go代码示例: 创建一个名为 `callc....
    99+
    2023-10-27
    go语言 c语言
  • C语言实现单位车辆调度管理
    本文实例为大家分享了C语言实现单位车辆调度管理的具体代码,供大家参考,具体内容如下 单位车辆信息包括:车牌号、车型、载重(客)量,车牌,生产厂家,出厂日期,购买日期,购买单价等;车辆...
    99+
    2024-04-02
  • laravel6中怎么实现队列与任务调度
    本篇文章为大家展示了laravel6中怎么实现队列与任务调度,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。(一)队列实现在laravel中,队列的实现我们只需要通过操作,就能实现,在实现的前提,我们...
    99+
    2023-06-20
  • Python怎么实现任务调度并行算法
    本篇内容介绍了“Python怎么实现任务调度并行算法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!本来自己想先使用Java来写一个版本,然后...
    99+
    2023-06-04
  • 如何在go语言中实现分布式任务调度的功能
    在Go语言中实现分布式任务调度功能可以借助一些开源项目和库来简化开发过程。以下是一个基本的实现步骤:1. 使用Go语言编写任务执行代...
    99+
    2023-10-12
    Go语言
  • 用C语言递归实现火车调度算法详解
    目录1、代码2、代码详解3、用二叉树表示调用过程4、思维导图笔者在李云清版的《数据结构》中第二章遇到了这道经典的火车调度题,经过对一些前辈的代码进行学习,以下将这段火车代码进行分析详...
    99+
    2024-04-02
  • c语言高精度加法怎么实现
    实现高精度加法可以通过将两个大整数分别存储在数组中,然后从低位到高位逐位相加,并考虑进位的情况来实现。以下是一个简单的C语言实现高精...
    99+
    2024-04-02
  • c语言跨文件调用变量怎么实现
    在C语言中,如果需要跨文件调用变量,可以通过使用`extern`关键字来实现。 假设有两个文件`file1.c`和`file2.c`...
    99+
    2023-10-27
    c语言
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作