加入收藏 | 设为首页 | 会员中心 | 我要投稿 应用网_丽江站长网 (http://www.0888zz.com/)- 科技、建站、数据工具、云上网络、机器学习!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

Linux 2.4调度系统分析--转

发布时间:2021-01-24 12:12:15 所属栏目:Linux 来源:网络整理
导读:副标题#e# 简介:?本文详尽地分析了Linux 2.4内核中调度系统的工作原理,特别是i386体系结构下SMP系统的调度表现。通过对2.4调度系统实现原理及其细节的分析,文章在文末指出了2.4调度系统在功能上、实时性上以及多处理机系统表现上存在的不足,为后继的2.6

找到合适的CPU后,reschedule_idle()就会将目标进程(正在该CPU上运行的进程,可能是idle_task)的need_resched置为1,以便调度器能够工作(见"调度器工作时机")。同时,因为idle_task很多情况下都使cpu处于停机(halt)状态以节电,所以有必要调用smp_send_reschedule(cpu)向cpu发RESCHEDULE_VECTOR中断(通过IPI接口),以唤醒该cpu。

注:对于目标进程是idle_task的情况,还要判断它的need_resched标志位,仅当它为0的时候才会启动调度,因为非0状态的idle_task本身一直都在检查need_resched值,它自己会启动schedule()(见下"IDLE进程")。

G. clear

调度器工作的结果有两种:发生了切换、没有发生切换,但调度器退出前的清理工作是一样的,就是恢复新进程的状态。主要包含两个动作:

  • 清被切换走的进程的SCHED_YIELD位(不管它是否置位);
  • 如果新进程(p)的lock_depth大于等于0,则重新为核心锁kernel_flag加锁(见上"相关锁")。

调度器的启动通常有两种方式:

A. 主动式

在核心应用中直接调用schedule()。这通常发生在因等待核心事件而需要将进程置于挂起(休眠)状态的时候--这时应该主动请求调度以方便其他进程使用CPU。下面就是一个主动调度的例子:

mousedev->wait,&wait); current->state = TASK_INTERRUPTIBLE; while (!list->ready) { if (file->f_flags & O_NONBLOCK) { retval = -EAGAIN; break; } if (signal_pending(current)) { retval = -ERESTARTSYS; break; } schedule(); } current->state = TASK_RUNNING; /* 这一句实际上可以省略,因为进程的状态在唤醒过程中就已经恢复到TASK_RUNNING了 */ remove_wait_queue(&list->mousedev->wait,&wait); 其过程通常可分为四步:

  • 将进程添加到事件等待队列中;
  • 置进程状态为TASK_INTERRUPTIBLE(或TASK_UNINTERRUPTIBLE);
  • 在循环中检查等待条件是否满足,不满足则调用schedule(),满足了就退出循环;
  • 将进程从事件等待队列中删除。

从"调度器工作流程"中我们知道,调度器会将处于休眠状态的进程从就绪队列中删除,而只有就绪队列中的进程才有可能被调度到。将该进程重新放到就绪队列中的动作是在事件发生时的"唤醒"过程中完成的。在以上所示的鼠标驱动中,鼠标中断将调用mousedev_event()函数,该函数的最后就会使用wake_up_interruptible()唤醒等待鼠标事件的所有进程。wake_up_interruptible()将最终调用try_to_wake_up()函数:

state = TASK_RUNNING; if (task_on_runqueue(p)) goto out; add_to_runqueue(p); /* 添加到就绪队列中 */ if (!synchronous || !(p->cpus_allowed & (1 << smp_processor_id()))) reschedule_idle(p); /* 这种情况下调用wake_up(),synchronous总为0,此时,*/ /* 如果本CPU不适合运行该进程,则需要调用reschedule_idle()寻找合适的CPU */ success = 1; out: spin_unlock_irqrestore(&runqueue_lock,flags); return success; } 这时启动schedule()就是被动的了。

B. 被动式

在系统调用执行结束后,控制由核心态返回到用户态之前,Linux都将在ret_from_sys_call入口检查当前进程的need_resched值,如果该值为1,则调用schedule():

因此,只需要设置当前进程(current)的need_resched,就有机会启动调度器。通常有如下几种场合会设置need_resched:

  • update_process_times(),由时钟中断触发,负责管理除0号进程(idle进程)以外的其他各个进程的时间片消耗。如果当前进程(SCHED_FIFO实时进程除外)的时间片用完了(counter==0),则设置need_resched为1;(注意:此时并不计算或重置counter值,这个工作在所有进程的时间片都耗完以后在schedule()中进行)
  • reschedule_idle(),此函数的功能在"调度器工作流程"一节中已经详细描述了,不过,最经常的调用者是在某一事件等待队列上休眠的进程的唤醒过程--wake_up_process()及其他一系列wake_up函数(见上"主动式调度");
  • sched_setscheduler()、sched_yield()系统调用,以及系统初始化(rest_init()中)、创建新进程(do_fork()中)等从语义上就希望启动调度器工作的场合。

(编辑:应用网_丽江站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!