10.9让进程能够延时运行

10.9让进程能够延时运行

增加一个延时队列(C语言里面sleep()函数的底层原理)

让CPU定时扫描延时队列,然后task结构体在多加一个字段,用来表示延时队列的延时时间,然后CPU定时扫描这些字段,看定时的字段有没有自减到0,自减到0了就看延时队列里面有没有task,然后将延完时的task加到就绪队列的末尾

//task.h
typedef struct _task_t {
    ```
	int sleep_ticks;		// 睡眠时间,单位ms
    ```
}task_t;
void task_set_sleep(task_t *task, uint32_t ticks); //插入的是那个进程,想睡眠多久
void task_set_wakeup (task_t *task); //从休眠队列移出去
void sys_msleep (uint32_t ms); //延时多少毫秒
//task.c
/**
 * @brief 将任务加入睡眠状态
 */
void task_set_sleep(task_t *task, uint32_t ticks) {
    if (ticks <= 0) {
        return;
    }

    task->sleep_ticks = ticks;
    task->state = TASK_SLEEP;
    list_insert_last(&task_manager.sleep_list, &task->run_node); //将run_node插入sleep_list表项的末尾
}

/**
 * @brief 将任务从延时队列移除
 */
void task_set_wakeup (task_t *task) {
    list_remove(&task_manager.sleep_list, &task->run_node); //移出指定链表中的特定表项
}

/**
 * @brief 任务进入睡眠状态
 * 
 * @param ms 
 */
void sys_msleep (uint32_t ms) {
    // 至少延时1个tick
    if (ms < OS_TICK_MS) { //不能少于10ms,10ms/单位
        ms = OS_TICK_MS;
    }

    irq_state_t state = irq_enter_protection();

    // 从就绪队列移除,加入睡眠队列
    task_set_block(task_manager.curr_task);
    task_set_sleep(task_manager.curr_task, (ms + (OS_TICK_MS - 1))/ OS_TICK_MS); //向上取整的操作
    
    // 进行一次调度
    task_dispatch();

    irq_leave_protection(state);
}
//前面准备工作都搞好了,现在是具体怎么定时
/**
 * @brief 时间处理
 * 该函数在中断处理函数中调用
 */
void task_time_tick (void) { //定时中断处理
    task_t * curr_task = task_current();

    // 时间片的处理
    irq_state_t state = irq_enter_protection();
    if (--curr_task->slice_ticks == 0) 
        // 时间片用完,重新加载时间片
        // 对于空闲任务,此处减未用
        curr_task->slice_ticks = 10;

        // 调整队列的位置到尾部,不用直接操作队列
        task_set_block(curr_task);
        task_set_ready(curr_task);
    }
    
    // 睡眠处理
    list_node_t * curr = list_first(&task_manager.sleep_list);
    while (curr) {
        list_node_t * next = list_node_next(curr); //先将后继节点取出来,这里的顺序很重要

        task_t * task = list_node_parent(curr, task_t, run_node);
        if (--task->sleep_ticks == 0) {
            // 延时时间到达,从睡眠队列中移除,送至就绪队列
            task_set_wakeup(task);
            task_set_ready(task);
        }
        curr = next;
    }

    task_dispatch();
    irq_leave_protection(state);
}
  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值