OS-实现一个FCFS调度算法
原理
FCFS也叫先来先服务调度算法,是非常简单的一种调度算法,他基于队列的排队思想,调度器必须排队处理加入队列的任务,不能进行抢占,我们只需要使用一个队列的数据结构就能够很方便的实现
LINUX下的SCHED_FIFO调度策略和FCFS是不一样的,虽然都是排队,但是SCHED_FIFO是基于优先级的,高优先级可抢占的,当相同优先级时和FCFS相同
准备数据结构
- 队列(queue)
- 任务控制块(tcb)
queue
list_head是一个双向循环链表,我们可以用他来实现一个队列
typedef struct list_head {
struct list_head *next, *prev;
} list_t;
typedef struct sched_queue
{
struct list_head tasks_head;
} sched_queue_t;
ready队列
struct sched_queue g_readytorun;
初始化队列
void schedule_init(void)
{
INIT_LIST_HEAD(&g_readytorun.tasks_head);
}
入队
void sched_enqueue(sched_queue_t *sq, tcb_t *task)
{
assert(sq != NULL && task != NULL);
list_add_tail(&task->link_head, &sq->tasks_head);
}
出队
tcb_t *sched_dequeue(sched_queue_t *sq)
{
assert(sq != NULL);
tcb_t *task = NULL;
tcb_t *task_tmp = NULL;
list_for_each_entry_safe(task, task_tmp, &sq->tasks_head, link_head)
{
list_del_init(&task->link_head);
break;
}
return task;
}
tcb
typedef struct tcb
{
struct list_head link_head;
/* reserved */
} tcb_t;
什么时候会发生调度?
- 主动放弃cpu资源(sleep/suspend)
- 被动放弃cpu资源(mutex/semaphore)
schedule流程
调度流程图
伪代码
void schedule(void)
{
tcb_t *cur_task = current();
tcb_t *task = NULL;
tcb_t *task_tmp = NULL;
sched_queue_t *ready_queue = &g_readytorun;
list_for_each_entry_safe(task, task_tmp, &ready_queue->tasks_head, link_head)
{
if (cur_task != task)
{
list_del_init(&task->link_head);
list_add_tail(&task->link_head, &ready_queue->tasks_head);
task_switch(task);
break;
}
}
}
时间复杂度
FCFS的特点就是不可抢占,下一个任务的运行必须等待上一个任务释放CPU,每个任务的平均等待时间是很长的,这个时候就要合理的安排任务的执行运行时序。
这个调度算法的时间复杂度是O(1)的,一次就可以找到需要调度的任务。在实际业务中很少会使用到这种调度策略,他有着很明显的缺陷。