软件架构之时间片轮询

软件架构之时间片轮询

时间片轮询法是一种比较简单易用的系统架构之一,它对于系统中的任务调度算法是分时处理。核心思路是把 CPU 的时间分时给各个任务使用。我们常用的定时方法是定时器,把调度器放在定时中,可以简单的实现时间片轮询法。
废话不多,直接上代码。

//***软件架构之时间片轮询***//

#include<stdio.h>

#define TASK_NUM (3)        //任务数为3,有3个任务会使用此定时器定时
                            //任务数可以直接给定或可以根据任务数组长度去判断

//***声明任务结构体***//
typedef struct _TaskStruct
{
    int run_flag;                //任务执行标志位
    int timer;              //定时器当前值
    int interval_time;      //任务运行的时间间隔,隔多久调度一次,定时器的值
    int (*task)();     //任务回调函数
}TaskStruct;


//***任务函数***//
int task1 ()       //任务1
{
    printf("this is task1.\n");
    return 0;
}
int task2 ()       //任务2
{
    printf("this is task2.\n");
    return 0;
}
int task3 ()       //任务3
{
    printf("this is task3.\n");
    return 0;
}


//***定义任务结构体***//
static TaskStruct TaskComps[]=
{
    {0,4,4,task1},      //任务1
    {0,2,2,task2},      //任务2
    {0,3,3,task3},      //任务3
    //添加任务
};


//***任务标志位处理***//
void task_flag(void)
{
    int i ;
    for (i=0;i<TASK_NUM;i++)    //逐个执行3任务
    { 
        if (TaskComps[i].timer)       //定时器值不为0,即定时器时间未到
        {
            TaskComps[i].timer--;     //定时器值-1
            if (TaskComps[i].timer == 0)        //定时器值为0,定时时间到
            {
                TaskComps[i].timer = TaskComps[i].interval_time;    //恢复定时器初值,以便重新开始计数
                TaskComps[i].run_flag = 1;        //标志位置1,开始执行任务i
                printf(" RUN_FLAG %d \n",i+1);
            }           
        }  
    } 
} 
 


//***任务执行***//
 void task_process(void)
{
    int i;
    for (i=0;i<TASK_NUM;i++)    //逐个执行3任务
    {
        if (TaskComps[i].run_flag)       //标志位为1,任务执行
        {
            TaskComps[i].task();        //执行任务
            TaskComps[i].run_flag = 0;      //标志位清零
        }      
    } 
}


//***主函数***//
int main(void)
{
   
    //一般需要先对用到的模块进行初始化,然后开始任务的轮询
    while(1)
    { 
        printf("begin.\n");
        task_flag();	//此处必须把标志位处理的函数一起放进while循环里,否则程序不能正常运行。
        				//猜想原因是若将其不放进来,run_flag一直是0,task_process()也就无法进行。
        task_process();
        
    }    
}

程序某次的运行结果如下。可以看到,每次运行时,程序是先将run_flag置1,然后再执行任务,这没什么问题;但是,程序并不是刷新一个run_flag之后就执行相对应的任务,而是将所有run_flag全部刷新之后,再依次执行相对应的任务。

begin.
 RUN_FLAG 1
 RUN_FLAG 2
 RUN_FLAG 3
this is task1.
this is task2.
this is task3.
begin.
begin.
 RUN_FLAG 2
this is task2.
begin.
 RUN_FLAG 3
this is task3.
begin.
 RUN_FLAG 1
 RUN_FLAG 2
this is task1.
this is task2.
begin.
begin.
 RUN_FLAG 2
 RUN_FLAG 3
this is task2.
this is task3.
begin.
begin.
 RUN_FLAG 1
 RUN_FLAG 2
this is task1.
this is task2.
begin.
 RUN_FLAG 3
this is task3.
begin.
 RUN_FLAG 2
this is task2.

另一方面,仔细看下面的结果,我们很容易发现,程序并不是每次都按照任务1,任务2,任务3这样的顺序全部执行的,有时候一个周期内只执行任务2,或者任务3,或者执行两个任务,并不是每次都3个任务顺序执行。这是因为每个任务的执行时间不同,我们由在定义任务结构体时设置的参数决定的,是可以根据任务的需要自行设定的。

需要注意的是,时间片轮询里的任务应该尽可能短小精悍,若执行任务时间太长,会导致任务还没执行完系统就已经刷到下一个任务去了。

//***定义任务结构体***//
static TaskStruct TaskComps[]=
{
    {0,4,4,task1},      //任务1
    {0,2,2,task2},      //任务2
    {0,3,3,task3},      //任务3
    //添加任务
};
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值